betfury free boxes auto claimer bot with other faucets.


SUBMITTED BY: PimpDaddy

DATE: Aug. 16, 2022, 6:44 p.m.

FORMAT: Text only

SIZE: 393.8 kB

HITS: 586

  1. // ==UserScript==
  2. // @name [satology] Auto Claim Multiple Faucets with Monitor UI
  3. // @description Automatic rolls and claims for 50+ crypto faucets/PTC/miners (Freebitco.in BTC, auto promo code for 16 CryptosFaucet, FaucetPay, StormGain, etc)
  4. // @description Claim free ADA, BNB, BCH, BTC, DASH, DGB, DOGE, ETH, FEY, LINK, LTC, NEO, SHIB, STEAM, TRX, USDC, USDT, XEM, XRP, ZEC, ETC
  5. // @version 2.7.0
  6. // @author satology
  7. // @namespace satology.onrender.com
  8. // @homepage https://criptologico.com/tools/cc
  9. // @note IMPORTANT
  10. // @note 0. To start the script you need to navigate to https://criptologico.com/tools/cc
  11. // @note 1. You must have a hCaptcha solver installed to claim from most of the faucets. Check the discord if you need one
  12. // @note 2. If the faucets are opening popups/popunder despite having an ad blocker, you can install this script which is targeting specific ads of the faucets:
  13. // @note https://greasyfork.org/en/scripts/429739-closewindowbyname
  14. // @note 3. The following script might help you prevent the focus detection (countdown stops), allowing you to do PTCs on background window:
  15. // @note https://greasyfork.org/en/scripts/427254-preventpagevisibility
  16. // @note I would suggest changing the match tag to make it run only on the sites you want
  17. // @note - MAIN FEATURES ------------------------------------------------------------------------------------------------------------------------------------------------
  18. // @note > Automatic rolls and claims for faucets/PTCs/miners
  19. // @note > Accepts promotion codes (http://twitter.com/cryptosfaucets, free roll shortlinks) for CF 16 faucets
  20. // @note > Simple Monitor UI on top of a website to track progress (claims, next rolls, promo codes)
  21. // @note CONSIDERATIONS
  22. // @note 0. You need to enable popups on the Manager UI website to be able to open the faucets
  23. // @note 1. CF Faucets need to open in English to recognize the promo code status after processing
  24. // @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
  25. // @note (Search for localeStrings in the code)
  26. // @note 2. Autorolls will trigger ONLY when the faucet was opened by the Manager UI.
  27. // @note This is to allow users to navigate the websites normally when manually visiting them
  28. // @note 3. You can enable/disable faucets from the UI. By default they are all set to false.
  29. // @note It would be great if you could register using the open link next to each faucet on the list
  30. // @note 4. All data stored for tracking and to be displayed is stored locally in your environment. Nothing is uploaded.
  31. // @note ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  32. // @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
  33. // @note guarantee that the faucets won't ban your IP or account.
  34. // @note ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  35. // @grant GM_info
  36. // @grant GM_setValue
  37. // @grant GM_getValue
  38. // @grant window.close
  39. // @grant GM_openInTab
  40. // @grant window.onurlchange
  41. // @icon https://www.google.com/s2/favicons?domain=stormgain.com
  42. // @match https://app.stormgain.com/crypto-miner/
  43. // @match https://freecardano.com/*
  44. // @match https://freebinancecoin.com/*
  45. // @match https://freebitcoin.io/*
  46. // @match https://freedash.io/*
  47. // @match https://free-doge.com/*
  48. // @match https://freeethereum.com/*
  49. // @match https://freechainlink.io/*
  50. // @match https://free-ltc.com/*
  51. // @match https://freeneo.io/*
  52. // @match https://freesteam.io/*
  53. // @match https://free-tron.com/*
  54. // @match https://freeusdcoin.com/*
  55. // @match https://freetether.com/*
  56. // @match https://freenem.com/*
  57. // @match https://freeshibainu.com/*
  58. // @match https://coinfaucet.io/*
  59. // @match https://freebitco.in/
  60. // @match https://faucetpay.io/*
  61. // @match https://free-litecoin.com/*
  62. // @match https://www.free-ethereum.io/
  63. // @match https://www.free-ethereum.io/free/
  64. // @match https://bagi.co.in/*
  65. // @match https://keran.co/*
  66. // @match https://btc-ok.net/*
  67. // @match https://dash-ok.net/*
  68. // @match https://dgb-ok.net/*
  69. // @match https://doge-ok.net/*
  70. // @match https://eth-ok.net/*
  71. // @match https://ltc-ok.net/*
  72. // @match https://trx-ok.net/*
  73. // @match https://bigbtc.win/*
  74. // @match https://www.bestchange.com/*
  75. // @match https://bitking.biz/*
  76. // @match https://litking.biz/*
  77. // @match https://faucetok.net/*
  78. // @match https://betfury.io/boxes/all*
  79. // @match https://www.free-doge.io/
  80. // @match https://www.free-doge.io/free/
  81. // @match https://autofaucet.dutchycorp.space/login.php*
  82. // @match https://autofaucet.dutchycorp.space/roll.php*
  83. // @match https://autofaucet.dutchycorp.space/coin_roll.php*
  84. // @match https://express.dutchycorp.space/index.php*
  85. // @match https://express.dutchycorp.space/roll.php*
  86. // @match https://express.dutchycorp.space/coin_roll.php*
  87. // @match https://faucetcrypto.com/dashboard
  88. // @match https://faucetcrypto.com/task/faucet-claim
  89. // @match https://faucetcrypto.com/ptc/*
  90. // @match https://faucetcrypto.com/task/ptc-advertisement/*
  91. // @match https://faupig-bit.online/page/dashboard*
  92. // @match https://faupig-bit.online/account/login/not-logged-in
  93. // @match https://freepancake.com/*
  94. // @match https://getfreetrx.com/*
  95. // @match https://freegridco.in/*
  96. // @match https://freematic.com/*
  97. // @match https://helidrops.io/*
  98. // @match https://freebch.fun/page/dashboard*
  99. // @match https://freebch.fun/account/login/not-logged-in
  100. // @match https://james-trussy.com/*
  101. // @match https://cryptobaggiver.com/dogecoin-faucet/*
  102. // @match https://cryptobaggiver.com/ethereum-faucet/*
  103. // @match https://cryptobaggiver.com/litecoin-faucet/*
  104. // @match https://cryptobaggiver.com/bitcoin-cash-faucet/*
  105. // @match https://cryptobaggiver.com/digibyte-faucet/*
  106. // @match https://cryptobaggiver.com/dash-faucet/*
  107. // @match https://dogefaucet.cryptobaggiver.com/*
  108. // @match https://ethereumfaucet.cryptobaggiver.com/*
  109. // @match https://litecoinfaucet.cryptobaggiver.com/*
  110. // @match https://bitcoincashfaucet.cryptobaggiver.com/*
  111. // @match https://digibytefaucet.cryptobaggiver.com/*
  112. // @match https://dashfaucet.cryptobaggiver.com/*
  113. // @match https://www.only1024.com/f*
  114. // @match https://criptologico.com/tools/cc*
  115. // ==/UserScript==
  116. (function() {
  117. 'use strict';
  118. const localeConfig = {
  119. setToEnglish: true, // will set the faucets to English
  120. stringSearches: {
  121. promoCodeAccepted: 'roll',
  122. promoCodeUsed: 'already used',
  123. promoCodeInvalid: ['not found', 'only alphanumeric'],
  124. promoCodeExpired: ['ended']
  125. }
  126. };
  127. const K = Object.freeze({
  128. WebType: {
  129. CRYPTOSFAUCETS: 1,
  130. STORMGAIN: 2,
  131. FREEBITCOIN: 3,
  132. FAUCETPAY: 4,
  133. FREELITECOIN: 5,
  134. FREEETHEREUMIO: 6,
  135. BAGIKERAN: 7,
  136. OKFAUCET: 8,
  137. BIGBTC: 9,
  138. BESTCHANGE: 10,
  139. KINGBIZ: 11,
  140. BETFURYBOX: 13,
  141. FREEDOGEIO: 14,
  142. DUTCHYROLL: 15,
  143. FCRYPTO: 16,
  144. CPU: 17,
  145. CBG: 18,
  146. FPB: 19,
  147. G8: 20,
  148. FREEGRC: 21,
  149. HELI: 22,
  150. VIE: 23,
  151. O24: 24
  152. },
  153. CF: {
  154. UrlType: {
  155. HOME: 0,
  156. FREE: 1,
  157. CONTACTTWITTER: 2,
  158. PROMOTION: 3,
  159. STATS: 4,
  160. SETTINGS: 5,
  161. FREEROLLS: 6,
  162. IGNORE: 99
  163. },
  164. PromoStatus: {
  165. NOCODE: 0,
  166. PENDING: 1,
  167. ACCEPTED: 2,
  168. USEDBEFORE: 3,
  169. INVALID: 4,
  170. UNKNOWNERROR: 5,
  171. EXPIRED: 6
  172. },
  173. ReusableCodeSuggestions: ['q5rlm6ot3r', '55khv20st4', 'ykxlvmg9ja', 'vmuph8j0c6', 'd8fmqxjlma', 'rjnmzjs673', 'ki2r0jq5r0', '4obq1i3idd']
  174. },
  175. RandomInteractionLevel: {
  176. NONE: 0,
  177. LOW: 1,
  178. MEDIUM: 2,
  179. HIGH: 3
  180. },
  181. Integers: {
  182. HS_26_IN_MILLISECONDS: 93600000, //Using 26 hs instead of 24hs
  183. HS_2_IN_MILLISECONDS: 7200000 //and 2hs gap retry when code is flagged as USEDBEFORE
  184. },
  185. WalletType: {
  186. FP_MAIL: 100,
  187. FP_BTC: 101,
  188. FP_BNB: 102,
  189. FP_BCH: 103,
  190. FP_DASH: 104,
  191. FP_DGB: 105,
  192. FP_DOGE: 106,
  193. FP_ETH: 107,
  194. FP_FEY: 108,
  195. FP_LTC: 109,
  196. FP_TRX: 110,
  197. FP_USDT: 111,
  198. FP_ZEC: 112,
  199. FP_SOL: 113,
  200. EC: 200,
  201. BTC: 1,
  202. LTC: 2
  203. },
  204. ErrorType: {
  205. ERROR: 0,
  206. TIMEOUT: 1,
  207. NEED_TO_LOGIN: 2,
  208. ROLL_ERROR: 3,
  209. CLICK_ROLL_ERROR: 4,
  210. LOGIN_ERROR: 5,
  211. CLAIM_ERROR: 6,
  212. ADDRESS_ERROR: 7,
  213. MIN_WITHDRAW_ERROR: 8,
  214. IP_BAN: 9,
  215. IP_RESTRICTED: 10,
  216. IP_ERROR: 11,
  217. FORCE_CLOSED: 12,
  218. NO_FUNDS: 13,
  219. VERIFY_EMAIL: 14,
  220. NO_ADDRESS: 15,
  221. FAUCET_EMPTY: 16
  222. },
  223. CMC: {
  224. MULT: '-1',
  225. BTC: '1',
  226. LTC: '2',
  227. XRP: '52',
  228. DOGE: '74',
  229. DGB: '109',
  230. DASH: '131',
  231. USDT: '825',
  232. XEM: '873',
  233. ETH: '1027',
  234. STEEM: '1230',
  235. NEO: '1376',
  236. ZEC: '1437',
  237. BCH: '1831',
  238. BNB: '1839',
  239. TRX: '1958',
  240. LINK: '1975',
  241. ADA: '2010',
  242. USDC: '3408',
  243. SOL: '5426',
  244. SHIB: '5994',
  245. FEY: '10361',
  246. BFG: '11038',
  247. CAKE: '7186',
  248. GRC: '833',
  249. MATIC: '3890'
  250. }
  251. });
  252. let persistence, shared, manager, ui, CFPromotions, interactions, CFHistory, SiteProcessor;
  253. Element.prototype.isVisible = function() {
  254. return !!(this.offsetWidth||this.offsetHeight||this.getClientRects().length);
  255. };
  256. Element.prototype.isUserFriendly = function(selector) {
  257. let e = selector ? this.querySelector(selector) : this;
  258. return e && e.isVisible() ? e : null;
  259. };
  260. HTMLDocument.prototype.isUserFriendly = Element.prototype.isUserFriendly;
  261. Number.prototype.toDate = function() {
  262. return new Date(this);
  263. };
  264. String.prototype.clean = function() {
  265. let output = "";
  266. for (let i = 0; i < this.length; i++) {
  267. if (this.charCodeAt(i) <= 127) {
  268. output += this.charAt(i);
  269. }
  270. }
  271. return output;
  272. };
  273. Array.prototype.shuffle = function () {
  274. let currentIndex = this.length, temporaryValue, randomIndex;
  275. while (0 !== currentIndex) {
  276. randomIndex = Math.floor(Math.random() * currentIndex);
  277. currentIndex -= 1;
  278. temporaryValue = this[currentIndex];
  279. this[currentIndex] = this[randomIndex];
  280. this[randomIndex] = temporaryValue;
  281. }
  282. return this;
  283. };
  284. let helpers = {
  285. getPrintableTime: function (date = new Date()) {
  286. if (date == null) {
  287. return '';
  288. }
  289. return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2);
  290. },
  291. getPrintableDateTime: function (date) {
  292. if (date != null) {
  293. return ('0' + date.getDate()).slice(-2) + '/' + ('0' + (date.getMonth() + 1)).slice(-2) + ' ' + ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);
  294. } else {
  295. return '';
  296. }
  297. },
  298. getEnumText: function (enm, value) {
  299. return Object.keys(enm).find(key => enm[key] === value) || '_ERR';
  300. },
  301. randomMs: function (a, b){
  302. return a + (b - a) * Math.random();
  303. },
  304. addMinutes: function(mins, date = new Date()) {
  305. return date.setMinutes(date.getMinutes() + +mins);
  306. },
  307. randomInt: function(min, max) {
  308. min = Math.ceil(min);
  309. max = Math.floor(max);
  310. return Math.floor(Math.random() * (max - min + 1)) + min;
  311. },
  312. addMs: function(ms, date = new Date()) {
  313. return date.setMilliseconds(date.getMilliseconds() + ms);
  314. },
  315. getRandomMs: function(minute, rangeDiffInPercentage) { // Now will be a random value between minute and minute + rangeDiffPercentage%; Example if minute = 30 and rangeDiffPercentage = 5 => random in the range [30, 31.5]
  316. let msMin = minute * 60 * 1000;
  317. let msMax = msMin + rangeDiffInPercentage/100 * msMin;
  318. return helpers.randomMs(msMin, msMax);
  319. },
  320. hsToMs: function(hours) {
  321. return hours * 60 * 60 * 1000;
  322. },
  323. minToMs: function(min) {
  324. return min * 60 * 1000;
  325. },
  326. getEmojiForPromoStatus: function(promoStatus) {
  327. switch (promoStatus) {
  328. case K.CF.PromoStatus.NOCODE:
  329. return '⚪';
  330. break;
  331. case K.CF.PromoStatus.PENDING:
  332. return '⏳';
  333. break;
  334. case K.CF.PromoStatus.ACCEPTED:
  335. return '✔️';
  336. break;
  337. case K.CF.PromoStatus.USEDBEFORE:
  338. return '🕙';
  339. break;
  340. case K.CF.PromoStatus.INVALID:
  341. return '❌';
  342. break;
  343. case K.CF.PromoStatus.EXPIRED:
  344. return '📅';
  345. break;
  346. case K.CF.PromoStatus.UNKNOWNERROR:
  347. return '❗';
  348. break;
  349. }
  350. },
  351. getHost: function(url, withHttps = false) {
  352. if (url.includes('//')) {
  353. url = url.split('//')[1];
  354. }
  355. url = url.split('/')[0];
  356. return withHttps ? ('https://' + url) : url;
  357. },
  358. cf: {
  359. getUrlType: function(url) {
  360. if (url.endsWith('/free-rolls')) {
  361. return K.CF.UrlType.FREEROLLS;
  362. }
  363. if (url.split('?')[0].endsWith('/free')) {
  364. return K.CF.UrlType.FREE;
  365. }
  366. if (url.includes('/promotion/')) {
  367. return K.CF.UrlType.PROMOTION;
  368. }
  369. if (url.endsWith('/contact-twitter')) {
  370. return K.CF.UrlType.CONTACTTWITTER;
  371. }
  372. if (url.endsWith('/settings')) {
  373. return K.CF.UrlType.SETTINGS;
  374. }
  375. if (url.endsWith('/stats')) {
  376. return K.CF.UrlType.STATS;
  377. }
  378. if (url.endsWith('/')) {
  379. url = url.slice(0, -1);
  380. if (url == helpers.getHost(url, true)) {
  381. return K.CF.UrlType.HOME;
  382. }
  383. }
  384. return K.CF.UrlType.IGNORE;
  385. }
  386. },
  387. triggerMouseEvent: function (elm, eventType) {
  388. let clickEvent = document.createEvent('MouseEvents');
  389. clickEvent.initEvent (eventType, true, true);
  390. elm.dispatchEvent (clickEvent);
  391. },
  392. alternativeClick: function (elm) {
  393. helpers.triggerMouseEvent (elm, "mouseover");
  394. helpers.triggerMouseEvent (elm, "mousedown");
  395. helpers.triggerMouseEvent (elm, "mouseup");
  396. helpers.triggerMouseEvent (elm, "click");
  397. }
  398. }
  399. let objectGenerator = {
  400. createPersistence: function() {
  401. const prefix = 'autoWeb_';
  402. function save(key, value, parseIt = false) {
  403. GM_setValue(prefix + key, parseIt ? JSON.stringify(value) : value);
  404. };
  405. function load(key, parseIt = false) {
  406. let value = GM_getValue(prefix + key);
  407. if(value && parseIt) {
  408. value = JSON.parse(value);
  409. }
  410. return value;
  411. };
  412. return {
  413. save: save,
  414. load: load
  415. };
  416. },
  417. createShared: function() {
  418. let flowControl;
  419. let config = {};
  420. function initializeConfig() {
  421. // Defaults:
  422. config['devlog.enabled'] = false;
  423. config['devlog.maxLines'] = 200;
  424. config['defaults.extraInterval'] = true;
  425. config['defaults.timeout'] = 4;
  426. config['defaults.postponeMinutes'] = 65; //0: Random between min and max
  427. config['defaults.postponeMinutes.min'] = 65;
  428. config['defaults.postponeMinutes.max'] = 65;
  429. config['defaults.workInBackground'] = true;
  430. config['defaults.nextRun.useCountdown'] = true;
  431. config['defaults.nextRun'] = 60; //0: Random between min and max
  432. config['defaults.nextRun.min'] = 60;
  433. config['defaults.nextRun.max'] = 60;
  434. config['defaults.sleepMode'] = false;
  435. config['defaults.sleepMode.min'] = "00:00";
  436. config['defaults.sleepMode.max'] = "01:00";
  437. config['cf.autologin'] = false;
  438. config['cf.credentials.mode'] = 1;
  439. config['cf.credentials.email'] = 'YOUR@EMAIL.com';
  440. config['cf.credentials.password'] = 'YOURPASSWORD';
  441. config['cf.sleepHoursIfIpBan'] = 8;
  442. // config['fb.activateRPBonus'] = true;
  443. // config['fp.hoursBetweenRuns'] = 6;
  444. config['fp.maxTimeInMinutes'] = 15;
  445. config['bk.withdrawMode'] = "0";
  446. config['bk.hoursBetweenWithdraws'] = 4;
  447. config['bk.sleepMinutesIfIpBan'] = 75;
  448. config['bestchange.address'] = '101';
  449. config['ui.runtime'] = 0;
  450. config['fpb.credentials.mode'] = 2;
  451. config['fpb.credentials.username'] = 'YOUR_USERNAME';
  452. config['fpb.credentials.password'] = 'YOURPASSWORD';
  453. config['bigbtc.postponeMinutes'] = '0';
  454. config['fbch.credentials.mode'] = 2;
  455. config['fbch.credentials.username'] = 'YOUR_USERNAME';
  456. config['fbch.credentials.password'] = 'YOURPASSWORD';
  457. config['jtfey.credentials.mode'] = 2;
  458. config['jtfey.credentials.username'] = 'YOUR_USERNAME';
  459. config['jtfey.credentials.password'] = 'YOURPASSWORD';
  460. let storedData = persistence.load('config', true);
  461. if(storedData) {
  462. for (const prop in config) {
  463. if(storedData.hasOwnProperty(prop)) {
  464. config[prop] = storedData[prop];
  465. }
  466. }
  467. }
  468. config.version = GM_info.script.version;
  469. // console.log('VERSION:', config.version);
  470. };
  471. function getConfig() {
  472. return config;
  473. };
  474. function updateConfig(items) {
  475. items.forEach( function (item) {
  476. config[item.prop] = item.value;
  477. });
  478. persistence.save('config', config, true);
  479. };
  480. function devlog(msg, elapsed = false, reset = false) {
  481. if(!config['devlog.enabled']) {
  482. return;
  483. }
  484. let log;
  485. if(reset) {
  486. log = [`${helpers.getPrintableTime()}|Log cleared`];
  487. } else {
  488. log = persistence.load('devlog', true);
  489. log = log ?? [];
  490. }
  491. if(msg) {
  492. let previous;
  493. try {
  494. previous = log[log.length - 1].split('|')[1];
  495. } catch {}
  496. if(elapsed && (previous == msg)) {
  497. log[log.length - 1] = `${helpers.getPrintableTime()}|${msg}|[Elapsed time: ${elapsed} seconds]`;
  498. } else {
  499. log.push(`${helpers.getPrintableTime()}|${msg}`);
  500. }
  501. }
  502. if(log.length > 200) {
  503. log.splice(0, log.length - 200);
  504. }
  505. persistence.save('devlog', log, true);
  506. };
  507. function getDevLog() {
  508. let log;
  509. log = persistence.load('devlog', true);
  510. if(log) {
  511. return log;
  512. }
  513. };
  514. function isOpenedByManager() {
  515. loadFlowControl();
  516. if(!flowControl) {
  517. return false;
  518. }
  519. shared.devlog(`Visit to: ${flowControl.url}`);
  520. if (flowControl.type == K.WebType.CBG) {
  521. if (window.location.href.includes(flowControl.url) || window.location.href.includes(flowControl.host)) {
  522. shared.devlog(`Visit [CBG] returning true`);
  523. return true;
  524. } else {
  525. shared.devlog(`Visit [CBG] returning false`);
  526. return false;
  527. }
  528. // // Ignore if full domain
  529. // if(flowControl.host == window.location.host) {
  530. // return false;
  531. // }
  532. } else if (flowControl.host != window.location.host) {
  533. return false;
  534. }
  535. if(flowControl.opened && flowControl.type != K.WebType.FAUCETPAY && flowControl.type != K.WebType.BAGIKERAN) {
  536. return false;
  537. }
  538. if(flowControl.type == K.WebType.BAGIKERAN && !window.location.href.includes(flowControl.params.trackUrl)) {
  539. return false;
  540. }
  541. return true;
  542. };
  543. function setFlowControl(id, url, webType, params = null) {
  544. flowControl = {
  545. id: id,
  546. changedAt: Date.now(),
  547. url: url,
  548. host: url.host,
  549. type: webType,
  550. opened: false,
  551. error: false,
  552. result: {}
  553. };
  554. if(params) {
  555. flowControl.params = params;
  556. }
  557. saveFlowControl();
  558. };
  559. function wasVisited(expectedId) {
  560. loadFlowControl();
  561. return flowControl.id == expectedId && flowControl.opened;
  562. };
  563. function hasErrors(expectedId) {
  564. return flowControl.id == expectedId && flowControl.error;
  565. };
  566. function getResult() {
  567. return flowControl.result;
  568. };
  569. function getCurrent() {
  570. return flowControl;
  571. };
  572. function saveAndclose(runDetails, delay = 0) {
  573. markAsVisited(runDetails);
  574. shared.devlog(`${window.location.href} closing`);
  575. if(delay) {
  576. setTimeout(window.close, delay);
  577. } else {
  578. setTimeout(window.close, 1000);
  579. }
  580. };
  581. function loadFlowControl() {
  582. flowControl = persistence.load('flowControl', true);
  583. };
  584. function saveFlowControl() {
  585. persistence.save('flowControl', flowControl, true);
  586. };
  587. function markAsVisited(runDetails) {
  588. flowControl.opened = true;
  589. flowControl.result = runDetails;
  590. saveFlowControl();
  591. };
  592. function addError(errorType, errorMessage) {
  593. flowControl.error = true;
  594. flowControl.result.errorType = errorType;
  595. flowControl.result.errorMessage = errorMessage;
  596. saveFlowControl();
  597. };
  598. function closeWithError(errorType, errorMessage) {
  599. addError(errorType, errorMessage);
  600. shared.devlog(`${window.location.href} closing with error msg`);
  601. window.close();
  602. };
  603. function clearFlowControl() {
  604. flowControl = {};
  605. saveFlowControl();
  606. };
  607. function clearRetries() {
  608. loadFlowControl();
  609. flowControl.retrying = false;
  610. saveFlowControl();
  611. return false;
  612. };
  613. function isRetrying() {
  614. if(flowControl.retrying) {
  615. return true;
  616. }
  617. flowControl.retrying = true;
  618. saveFlowControl();
  619. return false;
  620. };
  621. function setProp(key, val) {
  622. flowControl[key] = val;
  623. saveFlowControl();
  624. };
  625. function getProp(key) {
  626. return flowControl[key];
  627. };
  628. initializeConfig();
  629. return {
  630. devlog: devlog,
  631. getDevLog: getDevLog,
  632. setFlowControl: setFlowControl,
  633. wasVisited: wasVisited,
  634. isOpenedByManager: isOpenedByManager,
  635. saveFlowControl: saveFlowControl,
  636. getCurrent: getCurrent,
  637. getResult: getResult,
  638. addError: addError,
  639. closeWindow: saveAndclose,
  640. closeWithError: closeWithError,
  641. updateWithoutClosing: markAsVisited,
  642. hasErrors: hasErrors,
  643. clearFlowControl: clearFlowControl,
  644. getConfig: getConfig,
  645. updateConfig: updateConfig,
  646. clearRetries: clearRetries,
  647. isRetrying: isRetrying,
  648. setProp: setProp,
  649. getProp: getProp
  650. };
  651. },
  652. createManager: function() {
  653. const STATUS = {
  654. INITIALIZING: 0,
  655. IDLE: 1,
  656. CLAIMING: 2
  657. };
  658. let timestamp = null;
  659. let timeWaiting = 0;
  660. let uiUpdatesInterval;
  661. let status = STATUS.INITIALIZING;
  662. let processTimer;
  663. let workingTab;
  664. let webList = [];
  665. let userWallet = [];
  666. let groups = [];
  667. groups.push({
  668. name: 'Default',
  669. color: '#fff',
  670. siteList: [], // ids?
  671. currentSite: null,
  672. status: STATUS.INITIALIZING
  673. });
  674. const sites = [
  675. { id: '1', name: 'CF ADA', cmc: '2010', coinRef: 'ADA', url: new URL('https://freecardano.com/free'), rf: '?ref=335463', type: K.WebType.CRYPTOSFAUCETS, clId: 45 },
  676. { id: '2', name: 'CF BNB', cmc: '1839', coinRef: 'BNB', url: new URL('https://freebinancecoin.com/free'), rf: '?ref=161127', type: K.WebType.CRYPTOSFAUCETS, clId: 42 },
  677. { id: '3', name: 'CF BTC', cmc: '1', coinRef: 'BTC', url: new URL('https://freebitcoin.io/free'), rf: '?ref=490252', type: K.WebType.CRYPTOSFAUCETS, clId: 40 },
  678. { id: '4', name: 'CF DASH', cmc: '131', coinRef: 'DASH', url: new URL('https://freedash.io/free'), rf: '?ref=124083', type: K.WebType.CRYPTOSFAUCETS, clId: 156 },
  679. { id: '5', name: 'CF ETH', cmc: '1027', coinRef: 'ETH', url: new URL('https://freeethereum.com/free'), rf: '?ref=204076', type: K.WebType.CRYPTOSFAUCETS, clId: 44 },
  680. { id: '6', name: 'CF LINK', cmc: '1975', coinRef: 'LINK', url: new URL('https://freechainlink.io/free'), rf: '?ref=78652', type: K.WebType.CRYPTOSFAUCETS, clId: 157 },
  681. { id: '7', name: 'CF LTC', cmc: '2', coinRef: 'LTC', url: new URL('https://free-ltc.com/free'), rf: '?ref=117042', type: K.WebType.CRYPTOSFAUCETS, clId: 47 },
  682. { id: '8', name: 'CF NEO', cmc: '1376', coinRef: 'NEO', url: new URL('https://freeneo.io/free'), rf: '?ref=100529', type: K.WebType.CRYPTOSFAUCETS, clId: 158 },
  683. { id: '9', name: 'CF STEAM', cmc: '1230', coinRef: 'STEEM', url: new URL('https://freesteam.io/free'), rf: '?ref=117686', type: K.WebType.CRYPTOSFAUCETS, clId: 49 },
  684. { id: '10', name: 'CF TRX', cmc: '1958', coinRef: 'TRX', url: new URL('https://free-tron.com/free'), rf: '?ref=145047', type: K.WebType.CRYPTOSFAUCETS, clId: 41 },
  685. { id: '11', name: 'CF USDC', cmc: '3408', coinRef: 'USDC', url: new URL('https://freeusdcoin.com/free'), rf: '?ref=100434', type: K.WebType.CRYPTOSFAUCETS, clId: 51 },
  686. { id: '12', name: 'CF USDT', cmc: '825', coinRef: 'USDT', url: new URL('https://freetether.com/free'), rf: '?ref=181230', type: K.WebType.CRYPTOSFAUCETS, clId: 43 },
  687. { id: '13', name: 'CF XEM', cmc: '873', coinRef: 'XEM', url: new URL('https://freenem.com/free'), rf: '?ref=295274', type: K.WebType.CRYPTOSFAUCETS, clId: 46 },
  688. { id: '14', name: 'CF XRP', cmc: '52', coinRef: 'XRP', url: new URL('https://coinfaucet.io/free'), rf: '?ref=808298', type: K.WebType.CRYPTOSFAUCETS, clId: 48 },
  689. { id: '15', name: 'StormGain', cmc: '1', url: new URL('https://app.stormgain.com/crypto-miner/'), rf: 'friend/BNS27140552', type: K.WebType.STORMGAIN, clId: 35 },
  690. { id: '16', name: 'CF DOGE', cmc: '74', coinRef: 'DOGE', url: new URL('https://free-doge.com/free'), rf: '?ref=97166', type: K.WebType.CRYPTOSFAUCETS, clId: 50 },
  691. { id: '17', name: 'FreeBitco.in', cmc: '1', url: new URL('https://freebitco.in/'), rf: '?r=41092365', type: K.WebType.FREEBITCOIN, clId: 36 },
  692. { id: '18', name: 'FaucetPay PTC', cmc: '1', url: new URL('https://faucetpay.io/ptc'), rf: '?r=41092365', type: K.WebType.FAUCETPAY, clId: 159 },
  693. // { id: '19', name: 'Free-Litecoin.com', cmc: '2', url: new URL('https://free-litecoin.com/'), rf: 'login?referer=1332950', type: K.WebType.FREELITECOIN, clId: 160 },
  694. // { id: '20', name: 'Free-Ethereum.io', cmc: '1027', url: new URL('https://www.free-ethereum.io/'), rf: '?referer=1064662', type: K.WebType.FREEETHEREUMIO, clId: 161 },
  695. { id: '21', name: 'Bagi BTC', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://bagi.co.in/bitcoin/'), rf: ['?ref=53706', '?ref=63428', '?ref=54350'], type: K.WebType.BAGIKERAN, clId: 52 },
  696. { id: '22', name: 'Bagi BNB', cmc: '1839', wallet: K.WalletType.FP_BNB, url: new URL('https://bagi.co.in/binance/'), rf: ['?ref=12529', '?ref=23852', '?ref=13847'], type: K.WebType.BAGIKERAN, clId: 142 },
  697. { id: '23', name: 'Bagi BCH', cmc: '1831', wallet: K.WalletType.FP_BCH, url: new URL('https://bagi.co.in/bitcoincash/'), rf: ['?ref=44242', '?ref=50185', '?ref=41957'], type: K.WebType.BAGIKERAN, clId: 143 },
  698. { id: '24', name: 'Bagi DASH', cmc: '131', wallet: K.WalletType.FP_DASH, url: new URL('https://bagi.co.in/dash/'), rf: ['?ref=32724', '?ref=38540', '?ref=40441'], type: K.WebType.BAGIKERAN, clId: 144 },
  699. { id: '25', name: 'Bagi DGB', cmc: '109', wallet: K.WalletType.FP_DGB, url: new URL('https://bagi.co.in/digibyte/'), rf: ['?ref=22664', '?ref=27872', '?ref=29669'], type: K.WebType.BAGIKERAN, clId: 147 },
  700. { id: '26', name: 'Bagi DOGE', cmc: '74', wallet: K.WalletType.FP_DOGE, url: new URL('https://bagi.co.in/dogecoin/'), rf: ['?ref=45047', '?ref=54217', '?ref=45568'], type: K.WebType.BAGIKERAN, clId: 145 },
  701. { id: '27', name: 'Bagi ETH', cmc: '1027', wallet: K.WalletType.FP_ETH, url: new URL('https://bagi.co.in/ethereum/'), rf: ['?ref=24486', '?ref=27799', '?ref=24847'], type: K.WebType.BAGIKERAN, clId: 152 },
  702. { id: '28', name: 'Bagi FEY', cmc: '10361', wallet: K.WalletType.FP_FEY, url: new URL('https://bagi.co.in/feyorra/'), rf: ['?ref=5049', '?ref=7433', '?ref=5318'], type: K.WebType.BAGIKERAN, clId: 153 },
  703. { id: '29', name: 'Bagi LTC', cmc: '2', wallet: K.WalletType.FP_LTC, url: new URL('https://bagi.co.in/litecoin/'), rf: ['?ref=48335', '?ref=57196', '?ref=48878'], type: K.WebType.BAGIKERAN, clId: 146 },
  704. { id: '30', name: 'Bagi TRX', cmc: '1958', wallet: K.WalletType.FP_TRX, url: new URL('https://bagi.co.in/tron/'), rf: ['?ref=22622', '?ref=31272', '?ref=23075'], type: K.WebType.BAGIKERAN, clId: 150 },
  705. { id: '31', name: 'Bagi USDT', cmc: '825', wallet: K.WalletType.FP_USDT, url: new URL('https://bagi.co.in/tether/'), rf: ['?ref=25462', '?ref=32491', '?ref=25981'], type: K.WebType.BAGIKERAN, clId: 151 },
  706. { id: '32', name: 'Bagi ZEC', cmc: '1437', wallet: K.WalletType.FP_ZEC, url: new URL('https://bagi.co.in/zcash/'), rf: ['?ref=9181', '?ref=15120', '?ref=9878'], type: K.WebType.BAGIKERAN, clId: 148 },
  707. { id: '33', name: 'Keran BTC', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://keran.co/BTC/'), rf: ['?ref=73729', '?ref=92353', '?ref=79321'], type: K.WebType.BAGIKERAN, clId: 53 },
  708. { id: '34', name: 'Keran BNB', cmc: '1839', wallet: K.WalletType.FP_BNB, url: new URL('https://keran.co/BNB/'), rf: ['?ref=19287', '?ref=31242', '?ref=20659'], type: K.WebType.BAGIKERAN, clId: 54 },
  709. { id: '35', name: 'Keran BCH', cmc: '1831', wallet: K.WalletType.FP_BCH, url: new URL('https://keran.co/BCH/'), rf: ['?ref=58232', '?ref=67326', '?ref=70759'], type: K.WebType.BAGIKERAN, clId: 30 },
  710. { id: '36', name: 'Keran DASH', cmc: '131', wallet: K.WalletType.FP_DASH, url: new URL('https://keran.co/DASH/'), rf: ['?ref=45229', '?ref=53041', '?ref=55716'], type: K.WebType.BAGIKERAN, clId: 127 },
  711. { id: '37', name: 'Keran DGB', cmc: '109', wallet: K.WalletType.FP_DGB, url: new URL('https://keran.co/DGB/'), rf: ['?ref=32788', '?ref=39527', '?ref=42014'], type: K.WebType.BAGIKERAN, clId: 129 },
  712. { id: '38', name: 'Keran DOGE', cmc: '74', wallet: K.WalletType.FP_DOGE, url: new URL('https://keran.co/DOGE/'), rf: ['?ref=73512', '?ref=85779', '?ref=89613'], type: K.WebType.BAGIKERAN, clId: 128 },
  713. { id: '39', name: 'Keran ETH', cmc: '1027', wallet: K.WalletType.FP_ETH, url: new URL('https://keran.co/ETH/'), rf: ['?ref=32226', '?ref=36427', '?ref=32676'], type: K.WebType.BAGIKERAN, clId: 37 },
  714. { id: '40', name: 'Keran FEY', cmc: '10361', wallet: K.WalletType.FP_FEY, url: new URL('https://keran.co/FEY/'), rf: ['?ref=6269', '?ref=9019', '?ref=6569'], type: K.WebType.BAGIKERAN, clId: 133 },
  715. { id: '41', name: 'Keran LTC', cmc: '2', wallet: K.WalletType.FP_LTC, url: new URL('https://keran.co/LTC/'), rf: ['?ref=69102', '?ref=80726', '?ref=84722'], type: K.WebType.BAGIKERAN, clId: 29 },
  716. { id: '42', name: 'Keran TRX', cmc: '1958', wallet: K.WalletType.FP_TRX, url: new URL('https://keran.co/TRX/'), rf: ['?ref=49686', '?ref=46544', '?ref=34485'], type: K.WebType.BAGIKERAN, clId: 162 },
  717. { id: '43', name: 'Keran USDT', cmc: '825', wallet: K.WalletType.FP_USDT, url: new URL('https://keran.co/USDT/'), rf: ['?ref=40582', '?ref=48907', '?ref=41009'], type: K.WebType.BAGIKERAN, clId: 132 },
  718. { id: '44', name: 'Keran ZEC', cmc: '1437', wallet: K.WalletType.FP_ZEC, url: new URL('https://keran.co/ZEC/'), rf: ['?ref=', '?ref=18976', '?ref=12487'], type: K.WebType.BAGIKERAN, clId: 130 },
  719. // { id: '45', name: 'OK Btc', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://btc-ok.net/'), rf: 'index.php?r=1QCD6cWJNVH4Cdnz85SQ2qtTkAwGr9fvUk', type: K.WebType.OKFAUCET },
  720. // { id: '46', name: 'OK Dash', cmc: '131', wallet: K.WalletType.FP_DASH, url: new URL('https://dash-ok.net/'), rf: 'index.php?r=Xbyi7Fk2NRmZ32SHpDhmpGHLa4NMokhmGR', type: K.WebType.OKFAUCET },
  721. // { id: '47', name: 'OK Dgb', cmc: '109', wallet: K.WalletType.FP_DGB, url: new URL('https://dgb-ok.net/'), rf: 'index.php?r=DSM93hgZuapnjeeDMe8spzwG9rMrw4sdua', type: K.WebType.OKFAUCET },
  722. // { id: '48', name: 'OK Doge', cmc: '74', wallet: K.WalletType.FP_DOGE, url: new URL('https://doge-ok.net/'), rf: 'index.php?r=DDaQWmD7vY1NhtK1M5Pno7sdccmgxNUfv1', type: K.WebType.OKFAUCET },
  723. // { id: '49', name: 'OK Eth', cmc: '1027', wallet: K.WalletType.FP_ETH, url: new URL('https://eth-ok.net/'), rf: 'index.php?r=0x7636f64a8241257b1edaf65ae943c66de87b1749', type: K.WebType.OKFAUCET },
  724. // { id: '50', name: 'OK Ltc', cmc: '2', wallet: K.WalletType.FP_LTC, url: new URL('https://ltc-ok.net/'), rf: 'index.php?r=MEmxLqYzZdMsEswUQkqL5aawT5UsqYwYgr', type: K.WebType.OKFAUCET },
  725. // { id: '51', name: 'OK Trx', cmc: '1958', wallet: K.WalletType.FP_TRX, url: new URL('https://trx-ok.net/'), rf: 'index.php?r=TSocuzJ6ADUoQ49v28BXN2jo3By6awwHvj', type: K.WebType.OKFAUCET },
  726. { id: '52', name: 'BigBtc', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://bigbtc.win/'), rf: '?id=39255652', type: K.WebType.BIGBTC, clId: 200 },
  727. { id: '53', name: 'BestChange', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://www.bestchange.com/'), rf: ['index.php?nt=bonus&p=1QCD6cWJNVH4Cdnz85SQ2qtTkAwGr9fvUk'], type: K.WebType.BESTCHANGE, clId: 163 },
  728. // { id: '54', name: 'Litking.biz', cmc: '2', url: new URL('https://litking.biz/'), rf: 'signup?r=159189', type: K.WebType.KINGBIZ, clId: 164 },
  729. // { id: '55', name: 'Bitking.biz', cmc: '1', url: new URL('https://bitking.biz/'), rf: 'signup?r=90003', type: K.WebType.KINGBIZ, clId: 165 },
  730. // { id: '56', name: 'OK Bch', cmc: '1831', wallet: K.WalletType.FP_BCH, url: new URL('https://faucetok.net/bch/'), rf: '?r=qz742nf2c30ktehlmn0pg6quqe8yuwp3evd75y8c0k', type: K.WebType.OKFAUCET }
  731. // { id: '57', name: 'OurBitco.in', cmc: '1', url: new URL('https://ourbitco.in/dashboard'), rf: '?r=gebcjvwpky', type: K.WebType.OURBITCOIN },
  732. { id: '58', name: 'BetFury BTC', cmc: '1', url: new URL('https://betfury.io/boxes/all'), rf: ['?r=608c5cfcd91e762043540fd9'], type: K.WebType.BETFURYBOX, clId: 1 },
  733. { id: '59', name: 'BetFury BNB', cmc: '1839', url: new URL('https://betfury.io/boxes/all'), rf: ['?r=608c5cfcd91e762043540fd9'], type: K.WebType.BETFURYBOX, clId: 1 },
  734. // { id: '60', name: 'Free-Doge.io', cmc: '74', url: new URL('https://www.free-doge.io/'), rf: '?referer=6695', type: K.WebType.FREEDOGEIO, clId: 166 },
  735. { id: '61', name: 'Dutchy', cmc: '-1', url: new URL('https://autofaucet.dutchycorp.space/roll.php'), rf: '?r=corecrafting', type: K.WebType.DUTCHYROLL, clId: 141 },
  736. { id: '62', name: 'Dutchy Monthly Coin', cmc: '-1', url: new URL('https://autofaucet.dutchycorp.space/coin_roll.php'), rf: '?r=corecrafting', type: K.WebType.DUTCHYROLL, clId: 141 },
  737. // { id: '63', name: 'Express', cmc: '-1', url: new URL('https://express.dutchycorp.space/roll.php'), rf: '?r=EC-UserId-428378', type: K.WebType.DUTCHYROLL },
  738. // { id: '64', name: 'Express Monthly Coin', cmc: '-1', url: new URL('https://express.dutchycorp.space/coin_roll.php'), rf: '?r=EC-UserId-428378', type: K.WebType.DUTCHYROLL },
  739. { id: '65', name: 'FCrypto Roll', cmc: '-1', url: new URL('https://faucetcrypto.com/dashboard'), rf: 'ref/704060', type: K.WebType.FCRYPTO, clId: 27 },
  740. // WIP { id: '66', name: 'CPU', cmc: '-1', url: new URL('https://www.coinpayu.com/dashboard'), rf: '?r=corecrafting', type: K.WebType.CPU },
  741. { id: '67', name: 'BetFury BFG', cmc: '11038', url: new URL('https://betfury.io/boxes/all'), rf: ['?r=608c5cfcd91e762043540fd9'], type: K.WebType.BETFURYBOX, clId: 1 },
  742. { id: '68', name: 'CF SHIBA', cmc: '5994', coinRef: 'SHIBA', url: new URL('https://freeshibainu.com/free'), rf: '?ref=18226', type: K.WebType.CRYPTOSFAUCETS, clId: 167 },
  743. { id: '69', name: 'Bagi SOL', cmc: '5426', wallet: K.WalletType.FP_SOL, url: new URL('https://bagi.co.in/solana/'), rf: ['?ref=2838'], type: K.WebType.BAGIKERAN, clId: 149 },
  744. { id: '70', name: 'Keran SOL', cmc: '5426', wallet: K.WalletType.FP_SOL, url: new URL('https://keran.co/SOL/'), rf: ['?ref=4249'], type: K.WebType.BAGIKERAN, clId: 131 },
  745. { id: '71', name: 'CBG Doge', cmc: '74', wallet: K.WalletType.FP_DOGE, url: new URL('https://cryptobaggiver.com/dogecoin-faucet/'), rf: ['?r=D8Xgghu5gCryukwmxidFpSmw8aAKon2mEQ'], type: K.WebType.CBG, clId: 110 },
  746. { id: '72', name: 'CBG Eth', cmc: '1027', wallet: K.WalletType.FP_ETH, url: new URL('https://cryptobaggiver.com/ethereum-faucet/'), rf: ['?r=0xC21FD989118b8C0Db6Ac2eC944B53C09F7293CC8'], type: K.WebType.CBG, clId: 111 },
  747. { id: '73', name: 'CBG Ltc', cmc: '2', wallet: K.WalletType.FP_LTC, url: new URL('https://cryptobaggiver.com/litecoin-faucet/'), rf: ['?r=MWSsGAQTYD7GH5o4oAehC8Et5PyMBfhnKK'], type: K.WebType.CBG, clId: 114 },
  748. { id: '74', name: 'CBG Bch', cmc: '1831', wallet: K.WalletType.FP_BCH, url: new URL('https://cryptobaggiver.com/bitcoin-cash-faucet/'), rf: ['?r=qq2qlpzs4rsn30utrumezpkzezpteqj92ykdgfeq5u'], type: K.WebType.CBG, clId: 112 },
  749. { id: '75', name: 'CBG Dgb', cmc: '109', wallet: K.WalletType.FP_DGB, url: new URL('https://cryptobaggiver.com/digibyte-faucet/'), rf: ['?r=DTn8mnXo655wdS78u2qSHHcqaiP5Z8Ewro'], type: K.WebType.CBG, clId: 113 },
  750. { id: '76', name: 'CBG Dash', cmc: '131', wallet: K.WalletType.FP_DASH, url: new URL('https://cryptobaggiver.com/dash-faucet/'), rf: ['?r=XfYJ3XmbCHA1HcCFb5Qnyiq5YFFGVZYZv6'], type: K.WebType.CBG, clId: 115 },
  751. { id: '77', name: 'FPig', cmc: '825', wallet: K.WalletType.FP_USDT, url: new URL('https://faupig-bit.online/page/dashboard'), rf: [''], type: K.WebType.FPB, clId: 154 },
  752. { id: '78', name: 'CF Cake', cmc: '7186', coinRef: 'CAKE', url: new URL('https://freepancake.com/free'), rf: '?ref=699', type: K.WebType.CRYPTOSFAUCETS, clId: 197 },
  753. { id: '79', name: 'GetFreeTRX', cmc: '1958', wallet: K.WalletType.FP_TRX, url: new URL('https://getfreetrx.com/'), rf: '?r=TK3ofbD3AyXotN2111UvnwCzr2YaW8Qmx7', type: K.WebType.G8, clId: 201 },
  754. { id: '80', name: 'FreeGRC', cmc: '833', url: new URL('https://freegridco.in/#free_roll'), rf: '', type: K.WebType.FREEGRC, clId: 207 },
  755. { id: '81', name: 'CF Matic', cmc: '3890', coinRef: 'MATIC', url: new URL('https://freematic.com/free'), rf: '?ref=6435', type: K.WebType.CRYPTOSFAUCETS, clId: 210 },
  756. { id: '82', name: 'Heli', cmc: '-1', url: new URL('https://helidrops.io/coins.php'), rf: 'OLPUAO', type: K.WebType.HELI, clId: 211 },
  757. // { id: '83', name: 'FreeBCH', cmc: '1831', wallet: K.WalletType.FP_BCH, url: new URL('https://freebch.fun/page/dashboard'), rf: ['?r=satology'], type: K.WebType.FPB, clId: 212 },
  758. { id: '84', name: 'JTFey', cmc: '-1', url: new URL('https://james-trussy.com/faucet'), rf: ['?r=corecrafting'], type: K.WebType.VIE, clId: 213 },
  759. { id: '85', name: 'O24', cmc: '1', wallet: K.WalletType.FP_BTC, url: new URL('https://www.only1024.com/f'), rf: ['?r=1QCD6cWJNVH4Cdnz85SQ2qtTkAwGr9fvUk'], type: K.WebType.O24, clId: 97 }
  760. ];
  761. const wallet = [
  762. { id: '101', name: 'FaucetPay BTC (Bitcoin)', type: K.WalletType.FP_BTC },
  763. { id: '102', name: 'FaucetPay BNB (Binance Coin)', type: K.WalletType.FP_BNB },
  764. { id: '103', name: 'FaucetPay BCH (Bitcoin Cash)', type: K.WalletType.FP_BCH },
  765. { id: '104', name: 'FaucetPay DASH (Dash)', type: K.WalletType.FP_DASH },
  766. { id: '105', name: 'FaucetPay DGB (DigiByte)', type: K.WalletType.FP_DGB },
  767. { id: '106', name: 'FaucetPay DOGE (Dogecoin)', type: K.WalletType.FP_DOGE },
  768. { id: '107', name: 'FaucetPay ETH (Ethereum)', type: K.WalletType.FP_ETH },
  769. { id: '108', name: 'FaucetPay FEY (Feyorra)', type: K.WalletType.FP_FEY },
  770. { id: '109', name: 'FaucetPay LTC (Litecoin)', type: K.WalletType.FP_LTC },
  771. { id: '110', name: 'FaucetPay TRX (Tron)', type: K.WalletType.FP_TRX },
  772. { id: '111', name: 'FaucetPay USDT (Tether TRC20)', type: K.WalletType.FP_USDT },
  773. { id: '112', name: 'FaucetPay ZEC (Zcash)', type: K.WalletType.FP_ZEC },
  774. { id: '113', name: 'FaucetPay SOL (Solana)', type: K.WalletType.FP_SOL },
  775. { id: '200', name: 'ExpressCrypto (EC-UserId-XXXXXX)', type: K.WalletType.EC },
  776. { id: '1', name: 'BTC Alternative Address', type: K.WalletType.BTC }
  777. // { id: '2', name: 'LTC Address', type: K.WalletType.LTC }
  778. ];
  779. async function start() {
  780. await loader.initialize();
  781. ui.init(getCFlist());
  782. update();
  783. ui.refresh(null, null, userWallet);
  784. uiUpdatesInterval = setInterval(readUpdateValues, 10000);
  785. processTimer = setTimeout(manager.process, 2000);
  786. };
  787. let loader = function() {
  788. async function initialize() {
  789. setTimestamp();
  790. await initializeWebList();
  791. initializeUserWallet();
  792. initializePromotions();
  793. initializeHistory();
  794. };
  795. async function initializeWebList() {
  796. await addSites();
  797. addStoredSitesData();
  798. // splitInSchedules();
  799. };
  800. async function addSites() {
  801. sites.forEach(x => webList.push(x));
  802. // Set some defaults
  803. webList.forEach(function (element, idx, arr) {
  804. arr[idx].enabled = false;
  805. arr[idx].lastClaim = 0;
  806. arr[idx].aggregate = 0;
  807. arr[idx].balance = 0;
  808. arr[idx].stats = {};
  809. arr[idx].nextRoll = null;
  810. arr[idx].params = {};
  811. arr[idx].firstRun = true;
  812. arr[idx].schedule = '#4a70e0';
  813. // arr[idx].credentials = {
  814. // mode: -1, // need: not implemented, off, useCredentials, useThirdParty
  815. // username: '',
  816. // password: ''
  817. // };
  818. // TODO: review
  819. if(arr[idx].type == K.WebType.BAGIKERAN) {
  820. arr[idx].lastWithdraw = new Date();
  821. }
  822. if (element.id == '17') { //17: FB.in
  823. arr[idx].params['custom.useWofRp'] = 0;
  824. arr[idx].params['custom.useFunRp'] = 0;
  825. }
  826. if (element.id == '15') { //15: SG
  827. arr[idx].params['defaults.nextRun.override'] = true;
  828. arr[idx].params['defaults.nextRun.useCountdown'] = true;
  829. arr[idx].params['defaults.nextRun'] = 0;
  830. arr[idx].params['defaults.nextRun.min'] = 15;
  831. arr[idx].params['defaults.nextRun.max'] = 20;
  832. }
  833. if (element.id == '18') { //18: FPPTC
  834. arr[idx].params['defaults.workInBackground.override'] = true;
  835. arr[idx].params['defaults.workInBackground'] = false;
  836. arr[idx].params['defaults.nextRun.override'] = true;
  837. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  838. arr[idx].params['defaults.nextRun'] = 0;
  839. arr[idx].params['defaults.nextRun.min'] = 300;
  840. arr[idx].params['defaults.nextRun.max'] = 360;
  841. }
  842. if (element.id == '52') { //52: BigBtc
  843. arr[idx].params['defaults.nextRun.override'] = true;
  844. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  845. arr[idx].params['defaults.nextRun'] = 0;
  846. arr[idx].params['defaults.nextRun.min'] = 15;
  847. arr[idx].params['defaults.nextRun.max'] = 40;
  848. }
  849. if (element.id == '57') { //57: OB
  850. arr[idx].params['defaults.nextRun.override'] = true;
  851. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  852. arr[idx].params['defaults.nextRun'] = 0;
  853. arr[idx].params['defaults.nextRun.min'] = 15;
  854. arr[idx].params['defaults.nextRun.max'] = 18;
  855. }
  856. if (element.id == '58' || element.id == '59' || element.id == '67') { //58, 59: BetFury x2 + 67: BFG
  857. arr[idx].params['defaults.nextRun.override'] = true;
  858. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  859. arr[idx].params['defaults.nextRun'] = 0;
  860. arr[idx].params['defaults.nextRun.min'] = 21;
  861. arr[idx].params['defaults.nextRun.max'] = 25;
  862. }
  863. if (element.id == '61' || element.id == '62') { //61, 62: Dutchy x2
  864. arr[idx].params['defaults.nextRun.override'] = true;
  865. arr[idx].params['defaults.nextRun.useCountdown'] = true;
  866. arr[idx].params['defaults.nextRun'] = 0;
  867. arr[idx].params['defaults.nextRun.min'] = 30;
  868. arr[idx].params['defaults.nextRun.max'] = 35;
  869. }
  870. if (element.id == '65') { //65: FCrypto
  871. arr[idx].params['defaults.workInBackground.override'] = true;
  872. arr[idx].params['defaults.workInBackground'] = false;
  873. arr[idx].params['defaults.nextRun.override'] = true;
  874. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  875. arr[idx].params['defaults.nextRun'] = 0;
  876. arr[idx].params['defaults.nextRun.min'] = 26;
  877. arr[idx].params['defaults.nextRun.max'] = 35;
  878. arr[idx].params['defaults.timeout.override'] = true;
  879. arr[idx].params['defaults.timeout'] = 3;
  880. arr[idx].params['defaults.postponeMinutes.override'] = true;
  881. arr[idx].params['defaults.postponeMinutes'] = 0;
  882. arr[idx].params['defaults.postponeMinutes.min'] = 12;
  883. arr[idx].params['defaults.postponeMinutes.max'] = 18;
  884. }
  885. // if (element.id == '71' || element.id == '72' || element.id == '73' || element.id == '74' || element.id == '75' || element.id == '76') {
  886. // arr[idx].params['defaults.nextRun.override'] = true;
  887. // arr[idx].params['defaults.nextRun.useCountdown'] = false;
  888. // arr[idx].params['defaults.nextRun'] = 0;
  889. // arr[idx].params['defaults.nextRun.min'] = 9;
  890. // arr[idx].params['defaults.nextRun.max'] = 22;
  891. // }
  892. if (element.id == '77') { //77: FPB
  893. arr[idx].params['defaults.nextRun.override'] = true;
  894. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  895. arr[idx].params['defaults.nextRun'] = 0;
  896. arr[idx].params['defaults.nextRun.min'] = 5;
  897. arr[idx].params['defaults.nextRun.max'] = 90;
  898. }
  899. if (element.id == '83') { //FreeBCH
  900. arr[idx].params['defaults.nextRun.override'] = true;
  901. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  902. arr[idx].params['defaults.nextRun'] = 0;
  903. arr[idx].params['defaults.nextRun.min'] = 5;
  904. arr[idx].params['defaults.nextRun.max'] = 35;
  905. }
  906. if (element.id == '84') { //JT
  907. arr[idx].params['defaults.nextRun.override'] = true;
  908. arr[idx].params['defaults.nextRun.useCountdown'] = false;
  909. arr[idx].params['defaults.nextRun'] = 0;
  910. arr[idx].params['defaults.nextRun.min'] = 22;
  911. arr[idx].params['defaults.nextRun.max'] = 45;
  912. }
  913. });
  914. };
  915. function addStoredSitesData() {
  916. let storedData = persistence.load('webList', true);
  917. if(storedData) {
  918. storedData.forEach( function (element) {
  919. let idx = webList.findIndex(x => x.id == element.id);
  920. if(idx != -1) {
  921. webList[idx].name = element.name ?? webList[idx].name;
  922. webList[idx].lastClaim = element.lastClaim ?? webList[idx].lastClaim;
  923. webList[idx].aggregate = element.aggregate ?? webList[idx].aggregate;
  924. webList[idx].balance = element.balance ?? webList[idx].balance;
  925. webList[idx].stats = element.stats ?? webList[idx].stats;
  926. webList[idx].enabled = element.enabled ?? webList[idx].enabled;
  927. webList[idx].schedule = element.schedule ?? webList[idx].schedule;
  928. if(!webList[idx].enabled) {
  929. webList[idx].nextRoll = null;
  930. } else {
  931. webList[idx].nextRoll = element.nextRoll ? new Date(element.nextRoll) : new Date();
  932. }
  933. if(element.lastWithdraw) {
  934. webList[idx].lastWithdraw = new Date(element.lastWithdraw);
  935. }
  936. if(element.params) {
  937. for (var p in element.params) {
  938. webList[idx].params[p] = element.params[p];
  939. }
  940. }
  941. webList[idx].firstRun = element.firstRun ?? webList[idx].firstRun;
  942. if(webList[idx].aggregate != 0 || webList[idx].balance != 0) {
  943. webList[idx].firstRun = false;
  944. }
  945. // webList[idx].params = element.params ?? webList[idx].params;
  946. }
  947. });
  948. } else {
  949. // webList.shuffle();
  950. }
  951. };
  952. function splitInSchedules() {
  953. let schedules = [];
  954. webList.forEach((x, idx, elm) => {
  955. if (x.type == 1) {
  956. x.schedule = '#a0a0a0';
  957. }
  958. if(!schedules[x.schedule]) {
  959. schedules[x.schedule] = []
  960. };
  961. schedules[x.schedule].push(elm);
  962. });
  963. };
  964. function initializeUserWallet() {
  965. addWallets();
  966. addStoredWalletData();
  967. };
  968. function addWallets() {
  969. wallet.forEach(x => userWallet.push(x));
  970. userWallet.forEach(function (element, idx, arr) {
  971. arr[idx].address = '';
  972. });
  973. };
  974. function addStoredWalletData() {
  975. let storedData = persistence.load('userWallet', true);
  976. if(storedData) {
  977. storedData.forEach( function (element) {
  978. let idx = userWallet.findIndex(x => x.id == element.id);
  979. if(idx != -1) {
  980. userWallet[idx].address = element.address ?? webList[idx].address;
  981. }
  982. });
  983. }
  984. };
  985. function initializePromotions() {
  986. let storedData = persistence.load('CFPromotions', true);
  987. if (storedData) {
  988. let allCFs = manager.getFaucetsForPromotion().map( cf => cf.id );
  989. storedData.forEach( function (element, idx, arr) {
  990. arr[idx].added = new Date(element.added);
  991. arr[idx].statusPerFaucet.forEach( function (el, i, a) {
  992. a[i].execTimeStamp = (el.execTimeStamp != null) ? new Date(el.execTimeStamp) : null;
  993. });
  994. // Add new CFs
  995. allCFs.forEach( function (cf) {
  996. if (!arr[idx].statusPerFaucet.find( x => x.id == cf )) {
  997. let newCf = { id: cf, status: 1, execTimeStamp: null };
  998. arr[idx].statusPerFaucet.push(newCf);
  999. }
  1000. });
  1001. });
  1002. CFPromotions.load(storedData);
  1003. }
  1004. };
  1005. function initializeHistory() {
  1006. CFHistory.initOrLoad();
  1007. };
  1008. function setTimestamp() {
  1009. timestamp = Date.now();
  1010. persistence.save('timestamp', timestamp);
  1011. };
  1012. function removeDisabledFaucets() {
  1013. webList = webList.filter(x => x.enabled);
  1014. };
  1015. return {
  1016. initialize: initialize
  1017. };
  1018. }();
  1019. function readUpdateValues(forceCheck = false) {
  1020. readPromoCodeValues();
  1021. readModalData();
  1022. if(groups[0].status == STATUS.IDLE || forceCheck) {
  1023. let updateDataElement = document.getElementById('update-data');
  1024. let updateValues = updateDataElement.innerText.clean();
  1025. if (updateValues != '') {
  1026. updateDataElement.innerText = '';
  1027. let updateObj = JSON.parse(updateValues);
  1028. if(updateObj.runAsap.changed) {
  1029. updateObj.runAsap.ids.forEach(function (element, idx, arr) {
  1030. try {
  1031. let itemIndex = webList.findIndex(x => x.id == element)
  1032. webList[itemIndex].enabled = true;
  1033. webList[itemIndex].nextRoll = new Date(754000 + idx);
  1034. ui.log(`${webList[itemIndex].name} updated to run ASAP`);
  1035. } catch (err) {
  1036. ui.log(`Error setting faucet to run ASAP: ${err}`);
  1037. }
  1038. });
  1039. }
  1040. if(updateObj.editSingle.changed) {
  1041. updateObj.editSingle.items.forEach(function (element, idx, arr) {
  1042. try {
  1043. let itemIndex = webList.findIndex(x => x.id == element.id);
  1044. webList[itemIndex].name = element.displayName;
  1045. if (webList[itemIndex].enabled != element.enabled) {
  1046. webList[itemIndex].enabled = element.enabled;
  1047. if(webList[itemIndex].enabled) {
  1048. webList[itemIndex].nextRoll = new Date(idx);
  1049. } else {
  1050. webList[itemIndex].nextRoll = null;
  1051. }
  1052. }
  1053. ui.log(`Faucet updated. New name: ${element.displayName}. Active: ${element.enabled}`);
  1054. } catch (err) {
  1055. ui.log(`Error updating faucet data: ${err}`);
  1056. }
  1057. });
  1058. }
  1059. if(updateObj.wallet.changed) {
  1060. updateObj.wallet.items.forEach(function (element) {
  1061. try {
  1062. let itemIndex = userWallet.findIndex(x => x.id == element.id);
  1063. userWallet[itemIndex].address = element.address;
  1064. ui.log(`Wallet Address updated [${userWallet[itemIndex].name}]: ${userWallet[itemIndex].address}`);
  1065. } catch (err) {
  1066. ui.log(`Error updating wallet/address: ${err}`);
  1067. }
  1068. });
  1069. ui.refresh(null, null, userWallet);
  1070. saveUserWallet();
  1071. }
  1072. if(updateObj.config.changed) {
  1073. try {
  1074. shared.updateConfig(updateObj.config.items);
  1075. ui.log(`Config updated. Reloading in a few seconds...`);
  1076. window.location.reload();
  1077. return;
  1078. } catch (err) {
  1079. ui.log(`Error updating config: ${err}`);
  1080. }
  1081. }
  1082. if(updateObj.site.changed) {
  1083. // console.log(JSON.stringify(updateObj));
  1084. updateObj.site.list.forEach( (x) => {
  1085. try {
  1086. updateSite(x.id, x.items);
  1087. } catch (err) {
  1088. ui.log(`Error updating site: ${err}`);
  1089. }
  1090. });
  1091. }
  1092. if(updateObj.runAsap.changed || updateObj.editSingle.changed || updateObj.site.changed) {
  1093. update(true);
  1094. process();
  1095. return;
  1096. }
  1097. }
  1098. }
  1099. if(forceCheck) {
  1100. process();
  1101. }
  1102. };
  1103. function updateSite(id, items) {
  1104. let idx = webList.findIndex(x => x.id == id);
  1105. if (idx > -1) {
  1106. webList[idx].params = webList[idx].params || {};
  1107. items.forEach( (item) => {
  1108. webList[idx].params[item.prop] = item.value;
  1109. });
  1110. ui.log(`Site ${webList[idx].name} updated`);
  1111. }
  1112. }
  1113. function readModalData() {
  1114. if(document.getElementById('modal-spinner').isVisible()) {
  1115. let targetObject = JSON.parse(document.getElementById('target-spinner').innerHTML);
  1116. let target = targetObject.id;
  1117. if (target == 'modal-ereport') {
  1118. let temp = shared.getDevLog();
  1119. document.getElementById('log-textarea').value = temp.join('\n');
  1120. } else if (target == 'modal-config') {
  1121. ui.refresh(null, null, null, shared.getConfig());
  1122. } else if (target == 'modal-site') {
  1123. let site = webList.find(x => x.id == targetObject.siteId);
  1124. ui.refresh(null, null, null, null, { site: site, config: shared.getConfig() });
  1125. }
  1126. document.getElementById('modal-spinner').classList.toggle('d-none');
  1127. document.getElementById(target).classList.toggle('d-none');
  1128. document.getElementById('target-spinner').innerHTML = '';
  1129. }
  1130. }
  1131. function update(sortIt = true) {
  1132. // let updateRollStats = groups[0].currentSite && groups[0].currentSite.type == K.WebType.CRYPTOSFAUCETS;
  1133. if(sortIt) {
  1134. webList.sort( function(a,b) {
  1135. if (a === b) {
  1136. return 0;
  1137. } else if (a.nextRoll === null && b.nextRoll === null) {
  1138. return a.id > b.id ? -1 : 1
  1139. } else if (a.nextRoll === null) {
  1140. return 1;
  1141. } else if (b.nextRoll === null) {
  1142. return -1;
  1143. } else {
  1144. return a.nextRoll.getTime() < b.nextRoll.getTime() ? -1 : 1;
  1145. }
  1146. });
  1147. groups[0].currentSite = webList[0];
  1148. }
  1149. saveWebList();
  1150. ui.refresh(webList, CFPromotions.getAll());
  1151. updateRollStatsSpan();
  1152. };
  1153. function saveWebList() {
  1154. const data = webList.map(function(x) {
  1155. let ret = {
  1156. id: x.id,
  1157. name: x.name,
  1158. lastClaim: x.lastClaim,
  1159. aggregate: x.aggregate,
  1160. balance: x.balance,
  1161. stats: x.stats,
  1162. nextRoll: x.nextRoll,
  1163. enabled: x.enabled,
  1164. params: x.params
  1165. };
  1166. if (x.lastWithdraw) {
  1167. ret.lastWithdraw = x.lastWithdraw;
  1168. }
  1169. return ret;
  1170. });
  1171. persistence.save('webList', data, true);
  1172. }
  1173. function saveUserWallet() {
  1174. const data = userWallet.map(x => {
  1175. return {
  1176. id: x.id,
  1177. address: x.address
  1178. };});
  1179. persistence.save('userWallet', data, true);
  1180. }
  1181. function process() {
  1182. if(isObsolete()) {
  1183. return;
  1184. }
  1185. timer.stopCheck();
  1186. if(groups[0].currentSite.nextRoll == null) {
  1187. ui.log(`All faucets are disabled. Click edit and select those you want to run, or just hit the 'Run ASAP' link at the Actions column...`);
  1188. clearTimeout(processTimer);
  1189. groups[0].status = STATUS.IDLE;
  1190. return;
  1191. }
  1192. if(groups[0].currentSite.nextRoll.getTime() < Date.now()) {
  1193. ui.log(`Opening ${groups[0].currentSite.name}`);
  1194. clearTimeout(processTimer);
  1195. groups[0].status = STATUS.CLAIMING;
  1196. open();
  1197. } else {
  1198. let timeUntilNext = groups[0].currentSite.nextRoll.getTime() - Date.now() + helpers.randomMs(1000, 2000);
  1199. // PROCESSING AGAIN LAST 'FORCE CLOSED' IN CASE WE HAVE A WINDOW OF TIME (MORE THAN TIMEOUT/2):
  1200. if (timeUntilNext > (shared.getConfig()['defaults.timeout'] * 60 * 1000 / 2)) {
  1201. let idx = -1;
  1202. for (let i = webList.length - 1; i >= 0; i--) {
  1203. if (webList[i].enabled && webList[i].stats && webList[i].stats.errors && webList[i].stats.errors.errorType == K.ErrorType.FORCE_CLOSED) {
  1204. idx = i;
  1205. break;
  1206. }
  1207. }
  1208. if (idx > -1) {
  1209. webList[idx].nextRoll = new Date(-20);
  1210. update(true);
  1211. process();
  1212. return;
  1213. }
  1214. }
  1215. ui.log(`Waiting ${(timeUntilNext/1000/60).toFixed(2)} minutes...`);
  1216. clearTimeout(processTimer);
  1217. processTimer = setTimeout(manager.process, timeUntilNext);
  1218. groups[0].status = STATUS.IDLE;
  1219. }
  1220. };
  1221. function isObsolete() {
  1222. let savedTimestamp = persistence.load('timestamp');
  1223. if (savedTimestamp && savedTimestamp > timestamp) {
  1224. ui.log('<b>STOPING EXECUTION!<b> A new Manager UI window was opened. Process should continue there');
  1225. clearInterval(uiUpdatesInterval);
  1226. return true;
  1227. }
  1228. return false;
  1229. };
  1230. function open(promoCode) {
  1231. let navUrl = groups[0].currentSite.url;
  1232. try {
  1233. if(promoCode) {
  1234. navUrl = new URL('promotion/' + promoCode, groups[0].currentSite.url.origin);
  1235. ui.log(`Opening ${groups[0].currentSite.name} with Promo Code [${promoCode}]`);
  1236. }
  1237. if (groups[0].currentSite.firstRun) {
  1238. if(Array.isArray(groups[0].currentSite.rf) && groups[0].currentSite.rf.length > 0) {
  1239. navUrl = new URL(navUrl.href + groups[0].currentSite.rf[helpers.randomInt(0, groups[0].currentSite.rf.length - 1)]);
  1240. }
  1241. }
  1242. let params = groups[0].currentSite.params || {};
  1243. if (groups[0].currentSite.wallet) {
  1244. //TODO: VALIDATE THAT ADDRESS EXISTS AND IS VALID!!!
  1245. try {
  1246. params.address = userWallet.find(x => x.type == groups[0].currentSite.wallet).address;
  1247. // console.log(params.address);
  1248. } catch {
  1249. shared.addError(K.ErrorType.NO_ADDRESS, 'You need to add your address to the wallet before claiming this faucet.');
  1250. ui.log(`Unable to launch ${groups[0].currentSite.name}: Address not detected > add it to the wallet.`);
  1251. moveNextAfterTimeoutOrError();
  1252. return;
  1253. }
  1254. }
  1255. if(groups[0].currentSite.type == K.WebType.BESTCHANGE) {
  1256. params.address = shared.getConfig()['bestchange.address'] == '1' ? userWallet.find(x => x.type == 1).address : params.address;
  1257. }
  1258. if(groups[0].currentSite.type == K.WebType.BAGIKERAN) {
  1259. params.doWithdraw = getDoWithdraw(groups[0].currentSite.lastWithdraw);
  1260. params.doSignOut = (groups[0].currentSite.wallet == K.WalletType.FP_BCH ? true : false);
  1261. params.trackUrl = groups[0].currentSite.url;
  1262. }
  1263. params.cmc = groups[0].currentSite.cmc;
  1264. if(groups[0].currentSite.type == K.WebType.FPB) {
  1265. switch(groups[0].currentSite.id) {
  1266. case '77':
  1267. params.sitePrefix = 'fpb';
  1268. break;
  1269. case '83':
  1270. params.sitePrefix = 'fbch';
  1271. break;
  1272. // case '84':
  1273. // params.sitePrefix = 'jtfey';
  1274. // break;
  1275. }
  1276. }
  1277. // TODO: create credentials on site level
  1278. if(groups[0].currentSite.type == K.WebType.VIE) {
  1279. params.credentials = {
  1280. mode: shared.getConfig()['jtfey.credentials.mode'],
  1281. username: shared.getConfig()['jtfey.credentials.username'],
  1282. password: shared.getConfig()['jtfey.credentials.password']
  1283. };
  1284. }
  1285. shared.setFlowControl(groups[0].currentSite.id, navUrl, groups[0].currentSite.type, params);
  1286. setTimeout(manager.resultReader, 15000);
  1287. // Try to close old workingTab if still opened
  1288. if (workingTab && !workingTab.closed) {
  1289. try {
  1290. shared.devlog(`Tab closed from Manager`);
  1291. workingTab.close();
  1292. } catch {
  1293. shared.devlog(`ERROR: unable to close tab from Manager`);
  1294. }
  1295. } else {
  1296. shared.devlog(`No open tabs detected`);
  1297. }
  1298. timer.startCheck(groups[0].currentSite.type);
  1299. let noSignUpList = [ K.WebType.BESTCHANGE, K.WebType.CBG, K.WebType.G8, K.WebType.O24 ];
  1300. let hrefOpener = navUrl.href;
  1301. if (noSignUpList.includes(groups[0].currentSite.type)) {
  1302. hrefOpener = (new URL(groups[0].currentSite.clId, 'https://criptologico.com/goto/')).href;
  1303. }
  1304. workingTab = GM_openInTab(hrefOpener, { active: !getCustomOrDefaultVal('defaults.workInBackground', useOverride('defaults.workInBackground')) });
  1305. } catch(err) {
  1306. ui.log(`Error opening tab: ${err}`)
  1307. }
  1308. };
  1309. function getDoWithdraw(lastWithdraw) {
  1310. switch (shared.getConfig()['bk.withdrawMode']) {
  1311. case "0":
  1312. return false;
  1313. break;
  1314. case "2":
  1315. return true;
  1316. break;
  1317. case "1":
  1318. if(lastWithdraw == null) {
  1319. return true;
  1320. }
  1321. return (lastWithdraw && ( (Date.now() - lastWithdraw.getTime()) > helpers.hsToMs(shared.getConfig()['bk.hoursBetweenWithdraws'])));
  1322. break;
  1323. default:
  1324. return false;
  1325. }
  1326. return false;
  1327. }
  1328. function resultReaderV2() {
  1329. if(isObsolete()) {
  1330. return;
  1331. }
  1332. let active = shared.getCurrent();
  1333. switch(active.status) {
  1334. case 'STARTING':
  1335. return;
  1336. case 'WORKING':
  1337. return;
  1338. case 'PARTIAL_RESULTS':
  1339. return;
  1340. case 'FINISHED':
  1341. return;
  1342. }
  1343. }
  1344. // REFACTOR
  1345. function resultReader() {
  1346. if(isObsolete()) {
  1347. return;
  1348. }
  1349. if ( ( (groups[0].currentSite.type == K.WebType.FAUCETPAY && timeWaiting < shared.getConfig()['fp.maxTimeInMinutes'] * 60) )
  1350. && workingTab && !workingTab.closed ) {
  1351. timeWaiting += 15;
  1352. ui.log(`Waiting for ${groups[0].currentSite.name} results...`, timeWaiting);
  1353. setTimeout(manager.resultReader, 15000);
  1354. return;
  1355. }
  1356. if(shared.wasVisited(groups[0].currentSite.id)) {
  1357. let result = shared.getResult();
  1358. if (result) {
  1359. updateWebListItem(result);
  1360. if (result.closeParentWindow) {
  1361. ui.log(`Closing working tab per process request`);
  1362. closeWorkingTab();
  1363. }
  1364. if ( (groups[0].currentSite.type == K.WebType.CRYPTOSFAUCETS) &&
  1365. ( (result.claimed) || (result.promoStatus && result.promoStatus != K.CF.PromoStatus.ACCEPTED) )) {
  1366. let promoCode = CFPromotions.hasPromoAvailable(groups[0].currentSite.id);
  1367. if (promoCode) {
  1368. timeWaiting = 0;
  1369. update(false);
  1370. open(promoCode);
  1371. return;
  1372. }
  1373. }
  1374. if ( groups[0].currentSite.type == K.WebType.BAGIKERAN && shared.getCurrent().params.doWithdraw && !result.withdrawnAmount) {
  1375. if(!result.withdrawing) {
  1376. shared.updateWithoutClosing({ withdrawing: true });
  1377. update(false);
  1378. timeWaiting = 0;
  1379. }
  1380. if (hasTimedOut()) {
  1381. if(groups[0].currentSite.stats.countTimeouts) {
  1382. groups[0].currentSite.stats.countTimeouts += 1;
  1383. } else {
  1384. groups[0].currentSite.stats.countTimeouts = 1;
  1385. }
  1386. ui.log(`Waited too much time for ${groups[0].currentSite.name} results: triggering timeout`);
  1387. moveNextAfterTimeoutOrError();
  1388. return;
  1389. }
  1390. if (shared.hasErrors(groups[0].currentSite.id)) {
  1391. groups[0].currentSite.stats.errors = shared.getResult();
  1392. ui.log(`${groups[0].currentSite.name} closed with error: ${helpers.getEnumText(K.ErrorType, groups[0].currentSite.stats.errors.errorType)} ${groups[0].currentSite.stats.errors.errorMessage}`);
  1393. if(sleepIfBan()) {
  1394. return;
  1395. }
  1396. moveNextAfterTimeoutOrError();
  1397. return;
  1398. }
  1399. timeWaiting += 15;
  1400. ui.log(`Waiting for ${groups[0].currentSite.name} withdraw...`, timeWaiting);
  1401. setTimeout(manager.resultReader, 15000);
  1402. return;
  1403. }
  1404. } else {
  1405. ui.log(`Unable to read last run result, for ID: ${groups[0].currentSite.id} > ${groups[0].currentSite.name}`);
  1406. }
  1407. timeWaiting = 0;
  1408. update(true);
  1409. readUpdateValues(true);
  1410. return;
  1411. } else {
  1412. timeWaiting += 15;
  1413. if (!shared.hasErrors(groups[0].currentSite.id) && !hasTimedOut()) {
  1414. ui.log(`Waiting for ${groups[0].currentSite.name} results...`, timeWaiting);
  1415. setTimeout(manager.resultReader, 15000);
  1416. return;
  1417. }
  1418. if (shared.hasErrors(groups[0].currentSite.id)) {
  1419. groups[0].currentSite.stats.errors = shared.getResult();
  1420. ui.log(`${groups[0].currentSite.name} closed with error: ${helpers.getEnumText(K.ErrorType,groups[0].currentSite.stats.errors.errorType)} ${groups[0].currentSite.stats.errors.errorMessage}`);
  1421. if(groups[0].currentSite.type == K.WebType.CBG) {
  1422. ui.log(`Closing working tab per process request`);
  1423. closeWorkingTab();
  1424. }
  1425. if(sleepIfBan()) {
  1426. return;
  1427. }
  1428. }
  1429. if (hasTimedOut()) {
  1430. if(groups[0].currentSite.stats.countTimeouts) {
  1431. groups[0].currentSite.stats.countTimeouts += 1;
  1432. } else {
  1433. groups[0].currentSite.stats.countTimeouts = 1;
  1434. }
  1435. ui.log(`Waited too much time for ${groups[0].currentSite.name} results: triggering timeout`);
  1436. }
  1437. moveNextAfterTimeoutOrError();
  1438. return;
  1439. }
  1440. };
  1441. function errorTreatment() {
  1442. //TODO: validate that stats.errors.errorType exists
  1443. shared.devlog(`@errorTreatment`);
  1444. try {
  1445. switch(groups[0].currentSite.stats.errors.errorType) {
  1446. case K.ErrorType.NEED_TO_LOGIN:
  1447. groups[0].currentSite.enabled = false;
  1448. groups[0].currentSite.nextRoll = null;
  1449. return true;
  1450. case K.ErrorType.FAUCET_EMPTY: // retry in 8 hours
  1451. groups[0].currentSite.enabled = true;
  1452. groups[0].currentSite.nextRoll = new Date(new Date().setHours(new Date().getHours() + 8));
  1453. return true;
  1454. }
  1455. } catch {}
  1456. return false;
  1457. }
  1458. function sleepIfBan() {
  1459. if( (groups[0].currentSite.stats.errors.errorType == K.ErrorType.IP_BAN && shared.getConfig()['cf.sleepHoursIfIpBan'] > 0)
  1460. || ( (groups[0].currentSite.stats.errors.errorType == K.ErrorType.IP_RESTRICTED || groups[0].currentSite.stats.errors.errorType == K.ErrorType.IP_BAN) && shared.getConfig()['bk.sleepMinutesIfIpBan'] > 0) ) {
  1461. if(groups[0].currentSite.type == K.WebType.CRYPTOSFAUCETS) {
  1462. webList.filter(x => x.enabled && x.type == K.WebType.CRYPTOSFAUCETS)
  1463. .forEach( function(el) {
  1464. el.nextRoll = sleepCheck(helpers.addMs(helpers.getRandomMs(shared.getConfig()['cf.sleepHoursIfIpBan'] * 60, 2)).toDate());
  1465. });
  1466. }
  1467. if(groups[0].currentSite.type == K.WebType.BAGIKERAN) {
  1468. webList.filter(x => x.enabled && x.type == K.WebType.BAGIKERAN && x.url.host == groups[0].currentSite.url.host)
  1469. .forEach( function(el) {
  1470. el.nextRoll = sleepCheck(helpers.addMs(helpers.getRandomMs(shared.getConfig()['bk.sleepMinutesIfIpBan'], 2)).toDate());
  1471. });
  1472. }
  1473. shared.clearFlowControl();
  1474. update(true);
  1475. timeWaiting = 0;
  1476. readUpdateValues(true);
  1477. return true;
  1478. }
  1479. return false;
  1480. }
  1481. function getCustomOrDefaultVal(param, useOverride = false) {
  1482. let val;
  1483. if (useOverride) {
  1484. if (groups[0].currentSite.params && groups[0].currentSite.params.hasOwnProperty(param)) {
  1485. val = groups[0].currentSite.params[param];
  1486. if (val != -1) {
  1487. return val;
  1488. }
  1489. }
  1490. }
  1491. // console.log(`Using Default for ${param}: ${shared.getConfig()[param]}`);
  1492. return shared.getConfig()[param];
  1493. }
  1494. function useOverride(param) {
  1495. let overrideFlag = param + '.override';
  1496. return groups[0].currentSite.params && groups[0].currentSite.params[overrideFlag];
  1497. }
  1498. function sleepCheck(nextRun) {
  1499. // console.log(`sleepCheck for next run: ${nextRun}`);
  1500. let useCustom = useOverride('defaults.sleepMode');
  1501. // console.log(`Using Overide for sleepCheck: ${useCustom}`);
  1502. let sleepMode = getCustomOrDefaultVal('defaults.sleepMode', useCustom);
  1503. if (sleepMode) {
  1504. let intNextRunTime = nextRun.getHours() * 100 + nextRun.getMinutes();
  1505. let min = getCustomOrDefaultVal('defaults.sleepMode.min', useCustom).replace(':', '');
  1506. let max = getCustomOrDefaultVal('defaults.sleepMode.max', useCustom).replace(':', '');
  1507. if (+min < +max) {
  1508. if (+min < intNextRunTime && intNextRunTime < +max) {
  1509. shared.devlog(`Sleep Mode [${min} to ${max}]: adjusting next run. NextRunTimeInt => ${intNextRunTime}`);
  1510. nextRun.setHours(max.slice(0, 2), max.slice(-2), 10, 10);
  1511. }
  1512. } else if (+min > +max) {
  1513. if (intNextRunTime > +min || intNextRunTime < +max) {
  1514. shared.devlog(`Sleep Mode [${max} to ${min}]: adjusting next run. NextRunTimeInt => ${intNextRunTime}`);
  1515. nextRun.setHours(max.slice(0, 2), max.slice(-2), 10, 10);
  1516. if (nextRun.getTime() < Date.now()) {
  1517. // add 1 day
  1518. nextRun.setDate(nextRun.getDate() + 1);
  1519. }
  1520. }
  1521. }
  1522. }
  1523. return nextRun;
  1524. }
  1525. function getNextRun(nextRollFromCountdown) {
  1526. let useCustom = useOverride('defaults.nextRun');
  1527. let useCountdown = getCustomOrDefaultVal('defaults.nextRun.useCountdown', useCustom);
  1528. let nextRunMode = getCustomOrDefaultVal('defaults.nextRun', useCustom);
  1529. let min = getCustomOrDefaultVal('defaults.nextRun.min', useCustom);
  1530. let max = getCustomOrDefaultVal('defaults.nextRun.max', useCustom);
  1531. let nextRun;
  1532. if (useCountdown && nextRollFromCountdown) {
  1533. nextRun = nextRollFromCountdown;
  1534. } else {
  1535. let minutes = (nextRunMode == 0) ? helpers.randomInt(min, max) : nextRunMode;
  1536. let msDelay = helpers.getRandomMs(minutes, 1);
  1537. nextRun = helpers.addMs(msDelay).toDate();
  1538. }
  1539. nextRun = sleepCheck(nextRun)
  1540. shared.devlog(`@getNextRun: ${nextRun}`);
  1541. return nextRun;
  1542. }
  1543. function moveNextAfterTimeoutOrError() {
  1544. let useCustom = useOverride('defaults.postponeMinutes');
  1545. let mode = getCustomOrDefaultVal('defaults.postponeMinutes', useCustom);
  1546. let min = getCustomOrDefaultVal('defaults.postponeMinutes.min', useCustom);
  1547. let max = getCustomOrDefaultVal('defaults.postponeMinutes.max', useCustom);
  1548. let minutes = (mode == 0) ? helpers.randomInt(min, max) : mode;
  1549. let msDelay = helpers.getRandomMs(minutes, 5);
  1550. groups[0].currentSite.nextRoll = sleepCheck(helpers.addMs(msDelay).toDate());
  1551. if(errorTreatment()) {
  1552. shared.devlog(`@moveNextAfterTimeoutOrError: errorTreatment => true`);
  1553. }
  1554. shared.devlog(`@moveNextAfterTimeoutOrError: ${groups[0].currentSite.nextRoll}`);
  1555. shared.clearFlowControl();
  1556. update(true);
  1557. timeWaiting = 0;
  1558. readUpdateValues(true);
  1559. }
  1560. function hasTimedOut() {
  1561. let val = getCustomOrDefaultVal('defaults.timeout', useOverride('defaults.timeout')) * 60;
  1562. return (timeWaiting > val);
  1563. };
  1564. function updateWebListItem(result) {
  1565. if (result.withdrawing) {
  1566. return;
  1567. }
  1568. ui.log(`Updating data: ${JSON.stringify(result)}`);
  1569. groups[0].currentSite.stats.countTimeouts = 0;
  1570. groups[0].currentSite.stats.errors = null;
  1571. if (result.withdrawnAmount && result.withdrawnAmount > 0) {
  1572. groups[0].currentSite.lastWithdraw = new Date();
  1573. groups[0].currentSite.balance += result.withdrawnAmount;
  1574. groups[0].currentSite.lastClaim = 0;
  1575. groups[0].currentSite.aggregate = 0;
  1576. return;
  1577. }
  1578. if (result.claimed) {
  1579. try {
  1580. result.claimed = parseFloat(result.claimed);
  1581. } catch { }
  1582. if(!isNaN(result.claimed)) {
  1583. groups[0].currentSite.lastClaim = result.claimed;
  1584. groups[0].currentSite.aggregate += result.claimed;
  1585. }
  1586. }
  1587. if(result.balance) {
  1588. groups[0].currentSite.balance = result.balance;
  1589. }
  1590. groups[0].currentSite.nextRoll = getNextRun(result.nextRoll ? result.nextRoll.toDate() : null);
  1591. if(result.promoStatus) {
  1592. CFPromotions.updateFaucetForCode(result.promoCode, groups[0].currentSite.id, result.promoStatus);
  1593. }
  1594. if(result.rolledNumber) {
  1595. CFHistory.addRoll(result.rolledNumber);
  1596. }
  1597. };
  1598. function readPromoCodeValues() {
  1599. let promoCodeElement = document.getElementById('promo-code-new');
  1600. let promoDataStr = promoCodeElement.innerText.clean();
  1601. if (promoDataStr == '') {
  1602. return;
  1603. }
  1604. let promoData = JSON.parse(promoDataStr);
  1605. if(promoData.action) {
  1606. switch (promoData.action) {
  1607. case 'FORCESTOPFAUCET':
  1608. console.log('manager needs to stop current running site');
  1609. groups[0].currentSite.enabled = false;
  1610. update(true);
  1611. window.location.reload();
  1612. promoCodeElement.innerText = '';
  1613. //ui.refresh with reload
  1614. break;
  1615. case 'ADD':
  1616. CFPromotions.addNew(promoData.code, promoData.repeatDaily);
  1617. promoCodeElement.innerText = '';
  1618. document.getElementById('promo-text-input').value = '';
  1619. toastr["info"]("Code " + promoData.code + " added!");
  1620. ui.log(`Promo code ${promoData.code} added`);
  1621. ui.refresh(null, CFPromotions.getAll());
  1622. break;
  1623. case 'REMOVEALLPROMOS':
  1624. CFPromotions.removeAll();
  1625. promoCodeElement.innerText = '';
  1626. toastr["info"]("Promo codes removed!");
  1627. ui.log(`Promo codes removed`);
  1628. ui.refresh(null, CFPromotions.getAll());
  1629. break;
  1630. case 'REMOVE':
  1631. if(CFPromotions.remove(promoData.id, promoData.code) != -1) {
  1632. ui.log(`Promo code ${promoData.code} removed`);
  1633. } else {
  1634. ui.log(`Unable to remove code ${promoData.code}`);
  1635. }
  1636. promoCodeElement.innerText = '';
  1637. ui.refresh(null, CFPromotions.getAll());
  1638. break;
  1639. }
  1640. }
  1641. };
  1642. function updateRollStatsSpan() {
  1643. let rollsSpanElement = document.getElementById('rolls-span');
  1644. rollsSpanElement.innerText = CFHistory.getRollsMeta().join(',');
  1645. };
  1646. function getCFlist() {
  1647. let items;
  1648. items = webList.filter(f => f.type === K.WebType.CRYPTOSFAUCETS);
  1649. items = items.map(x => {
  1650. return {
  1651. id: x.id,
  1652. name: x.coinRef
  1653. };});
  1654. items.sort((a, b) => (a.name > b.name) ? 1 : -1);
  1655. return items;
  1656. };
  1657. function closeWorkingTab() {
  1658. workingTab.close();
  1659. };
  1660. return{
  1661. init:start,
  1662. process: process,
  1663. resultReader: resultReader,
  1664. getFaucetsForPromotion: getCFlist,
  1665. readPromoCodeValues: readPromoCodeValues,
  1666. closeWorkingTab: closeWorkingTab
  1667. };
  1668. },
  1669. createUi: function() {
  1670. let injectables = {
  1671. managerJs: function () {
  1672. window.myBarChart = null;
  1673. window.landing = window.location.host;
  1674. window.sendErrorReport = function sendErrorReport() {
  1675. try {
  1676. let header = new Headers();
  1677. header.append("Content-Type", "application/json");
  1678. let description = document.getElementById("log-message").value;
  1679. let log = document.getElementById("log-textarea").value.split('\n');
  1680. let content = {"description":description, "log":log};
  1681. let opt = { method: "POST", header, mode: "cors", body: JSON.stringify(content) };
  1682. fetch("https://1d0103ec5a621b87ea27ffed3c072796.m.pipedream.net", opt).then(response => {
  1683. console.log(response);
  1684. }).catch(err => {
  1685. console.error("[error] " + err.message);
  1686. });
  1687. } catch { }
  1688. };
  1689. window.loadDlg = function loadDlg(id, siteId = null) {
  1690. document.querySelectorAll("#modal-dlg .modal-content").forEach(x => x.classList.add('d-none'));
  1691. if (id == "modal-ereport" || id == "modal-config" || id == "modal-site") {
  1692. document.getElementById("target-spinner").innerHTML = JSON.stringify({id: id, siteId: siteId});
  1693. document.getElementById("modal-spinner").classList.remove("d-none");
  1694. return;
  1695. } else if (id == 'model-slAlert') {
  1696. shortlinkAlert.load(id);
  1697. } else {
  1698. document.getElementById(id).classList.remove("d-none");
  1699. }
  1700. };
  1701. window.savePromoCode = function savePromoCode() {
  1702. var promoText = document.getElementById("promo-text-input");
  1703. var promoCode = document.getElementById("promo-code-new");
  1704. var promoDaily = document.getElementById("promo-daily");
  1705. var promoObject = { action: "ADD", code: promoText.value.trim(), repeatDaily: promoDaily.checked };
  1706. promoCode.innerHTML =JSON.stringify(promoObject);
  1707. toastr["info"]("Adding promo code: " + promoObject.code + "...");
  1708. promoText.value = '';
  1709. };
  1710. window.removePromoCode = function removePromoCode(id, code) {
  1711. var promoCode = document.getElementById("promo-code-new");
  1712. var promoObject = { action: "REMOVE", id: id, code: code };
  1713. promoCode.innerHTML =JSON.stringify(promoObject);
  1714. toastr["info"]("Removing promo code " + code);
  1715. };
  1716. window.getUpdateObject = function getUpdateObject() {
  1717. let updateObject;
  1718. var updateData = document.getElementById("update-data");
  1719. if (updateData.innerHTML != "") {
  1720. updateObject = JSON.parse(updateData.innerHTML);
  1721. } else {
  1722. updateObject = { runAsap: { ids: [], changed: false}, editSingle: { changed: false, items: [] }, wallet: { changed: false, items: []}, config: { changed: false, items: []}, site: { changed: false, list: []} };
  1723. }
  1724. return updateObject;
  1725. };
  1726. window.editList = function editList() {
  1727. document.querySelectorAll("#schedule-table-body td.em-input span").forEach(function (x) {
  1728. let val = x.innerHTML;
  1729. x.innerHTML = "<input type=\'text\' class=\'form-control form-control-sm\' data-original=\'" + val.trim() + "\' value=\'" + val.trim() + "\' />";
  1730. });
  1731. document.querySelectorAll("#schedule-table-body td.edit-status").forEach(function (x) {
  1732. let activeSwitch = x.querySelector("input");
  1733. x.classList.remove("d-none");
  1734. });
  1735. document.querySelectorAll(".em-only").forEach(x => x.classList.remove("d-none"));
  1736. document.querySelectorAll(".em-hide").forEach(x => x.classList.add("d-none"));
  1737. };
  1738. window.editListSave = function editListSave() {
  1739. let updateObject = getUpdateObject();
  1740. document.querySelectorAll("#schedule-table-body tr:not(.fake-row)").forEach(function (row) {
  1741. let textInputCell = row.querySelector(".em-input span");
  1742. let textInput = textInputCell.querySelector("input");
  1743. let activeSwitch = row.querySelector("td.edit-status input");
  1744. let single = { id: row.dataset.id, displayName: textInput.dataset.original, enabled: activeSwitch.dataset.original };
  1745. textInputCell.innerHTML = textInput.value;
  1746. if(textInput.dataset.original != textInput.value) {
  1747. single.displayName = textInput.value;
  1748. }
  1749. if(activeSwitch.dataset.original != Boolean(activeSwitch.checked)) {
  1750. single.enabled = Boolean(activeSwitch.checked);
  1751. }
  1752. if(textInput.dataset.original != textInput.value || activeSwitch.dataset.original != Boolean(activeSwitch.checked)) {
  1753. updateObject.editSingle.items.push(single);
  1754. updateObject.editSingle.changed = true;
  1755. }
  1756. });
  1757. if(updateObject.editSingle.changed) {
  1758. document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);
  1759. toastr["info"]("Data will be updated as soon as possible");
  1760. }
  1761. document.querySelectorAll(".em-only").forEach(x => x.classList.add("d-none"));
  1762. document.querySelectorAll(".em-hide").forEach(x => x.classList.remove("d-none"));
  1763. };
  1764. window.editListCancel = function editListCancel() {
  1765. document.querySelectorAll("#schedule-table-body td.em-input input").forEach(function(x) {
  1766. x.parentNode.innerHTML = x.dataset.original;
  1767. });
  1768. document.querySelectorAll(".em-only").forEach(x => x.classList.add("d-none"));
  1769. document.querySelectorAll(".em-hide").forEach(x => x.classList.remove("d-none"));
  1770. };
  1771. window.editWallet = {
  1772. save: function() {
  1773. let updateObject = getUpdateObject();
  1774. document.querySelectorAll("#wallet-table-body tr").forEach( function(row) {
  1775. let textInput = row.querySelector(".em-input input");
  1776. if(textInput.dataset.original != textInput.value) {
  1777. let single = { id: row.dataset.id, address: textInput.value.trim() };
  1778. updateObject.wallet.items.push(single);
  1779. updateObject.wallet.changed = true;
  1780. }
  1781. });
  1782. if(updateObject.wallet.changed) {
  1783. document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);
  1784. toastr["info"]("Wallet will be updated as soon as possible");
  1785. }
  1786. },
  1787. toggleJson: function(val) {
  1788. if (document.querySelector('#wallet-json').isVisible()) {
  1789. if(val != 'cancel') {
  1790. editWallet.fromJson();
  1791. }
  1792. } else {
  1793. editWallet.toJson();
  1794. }
  1795. document.querySelector('.footer-json').classList.toggle('d-none');
  1796. document.querySelector('.footer-table').classList.toggle('d-none');
  1797. document.querySelector('#wallet-table').classList.toggle('d-none');
  1798. document.querySelector('#wallet-json').classList.toggle('d-none');
  1799. },
  1800. toJson: function() {
  1801. let j = [];
  1802. document.querySelectorAll('#wallet-table-body tr').forEach(function (row) {
  1803. j.push({ id: row.dataset.id, address: row.querySelector('.em-input input').value });
  1804. });
  1805. document.querySelector('#wallet-json').value = JSON.stringify(j);
  1806. },
  1807. fromJson: function() {
  1808. let j = JSON.parse(document.querySelector('#wallet-json').value);
  1809. document.querySelectorAll('#wallet-table-body tr').forEach(function (row) {
  1810. let element = j.find(x => x.id == row.dataset.id);
  1811. if (element) {
  1812. row.querySelector('.em-input input').value = element.address;
  1813. }
  1814. });
  1815. },
  1816. cancel: function() {
  1817. document.querySelectorAll("#wallet-table-body .em-input input").forEach( function(x) {
  1818. x.value = x.dataset.original;
  1819. });
  1820. }
  1821. };
  1822. window.editConfig = {
  1823. save: function() {
  1824. let updateObject = getUpdateObject();
  1825. document.querySelectorAll("#modal-config [data-original][data-prop]").forEach(function(elm) {
  1826. let single = { prop: elm.dataset.prop, value: elm.dataset.value };
  1827. if(elm.dataset.original != elm.value && (elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") ) {
  1828. single.value = elm.value;
  1829. updateObject.config.items.push(single);
  1830. updateObject.config.changed = true;
  1831. } else if (elm.type == "checkbox" && ((elm.dataset.original == "0" && elm.checked) || (elm.dataset.original == "1" && !elm.checked)) ) {
  1832. single.value = elm.checked;
  1833. updateObject.config.items.push(single);
  1834. updateObject.config.changed = true;
  1835. }
  1836. });
  1837. if(updateObject.config.changed) {
  1838. document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);
  1839. toastr["info"]("Config will be updated as soon as possible");
  1840. }
  1841. },
  1842. cancel: function() {
  1843. document.querySelectorAll("#modal-config [data-original][data-prop]").forEach(function(elm) {
  1844. if(elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") {
  1845. elm.value = elm.dataset.original;
  1846. } else if (elm.type == "checkbox") {
  1847. elm.checked = (elm.dataset.original == "1" ? true : false)
  1848. }
  1849. });
  1850. }
  1851. };
  1852. window.editSite = {
  1853. save: function() {
  1854. let updateObject = getUpdateObject();
  1855. let faucet = { id: document.querySelector("#faucet-name").dataset.id, items: [] };
  1856. document.querySelectorAll("#modal-site [data-original][data-site-prop]").forEach(function(elm) {
  1857. let single = { prop: elm.dataset.siteProp, value: elm.dataset.original };
  1858. if(elm.dataset.original != elm.value && (elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") ) {
  1859. single.value = elm.value;
  1860. faucet.items.push(single);
  1861. updateObject.site.changed = true;
  1862. } else if (elm.type == "checkbox" && ((elm.dataset.original == "0" && elm.checked) || (elm.dataset.original == "1" && !elm.checked)) ) {
  1863. single.value = elm.checked;
  1864. faucet.items.push(single);
  1865. updateObject.site.changed = true;
  1866. }
  1867. });
  1868. if(updateObject.site.changed) {
  1869. updateObject.site.list.push(faucet);
  1870. document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);
  1871. toastr["info"]("Site will be updated as soon as possible");
  1872. }
  1873. },
  1874. cancel: function() {
  1875. document.querySelectorAll("#modal-site [data-original][data-site-prop]").forEach(function(elm) {
  1876. if(elm.type == "select-one" || elm.type == "text" || elm.type == "password" || elm.type == "number" || elm.type == "time") {
  1877. elm.value = elm.dataset.original;
  1878. } else if (elm.type == "checkbox") {
  1879. elm.checked = (elm.dataset.original == "1" ? true : false)
  1880. }
  1881. });
  1882. }
  1883. };
  1884. window.editEreport = {
  1885. save: function() {
  1886. sendErrorReport();
  1887. },
  1888. cancel: function() {
  1889. }
  1890. };
  1891. window.modalSave = function modalSave(content) {
  1892. switch(content) {
  1893. case "wallet":
  1894. editWallet.save();
  1895. break;
  1896. case "ereport":
  1897. editEreport.save();
  1898. break;
  1899. case "config":
  1900. editConfig.save();
  1901. break;
  1902. case "site":
  1903. editSite.save();
  1904. break;
  1905. case "slAlert":
  1906. shortlinkAlert.save();
  1907. break;
  1908. }
  1909. };
  1910. window.modalCancel = function modalCancel(content) {
  1911. if(content == "wallet") {
  1912. editWallet.cancel();
  1913. } else if ("ereport") {
  1914. editEreport.cancel();
  1915. }
  1916. document.querySelectorAll("modal-content").forEach(x => x.classList.add("d-none"));
  1917. };
  1918. window.updateValues = function updateValues(type, values) {
  1919. let updateObject = getUpdateObject();
  1920. if (type == "runAsap") {
  1921. updateObject.runAsap.ids.push(values.id);
  1922. updateObject.runAsap.changed = true;
  1923. document.getElementById("update-data").innerHTML = JSON.stringify(updateObject);
  1924. toastr["info"]("Faucet will be updated to run as soon as possible");
  1925. }
  1926. };
  1927. window.confirmable = {
  1928. open: function (req, details = null, params = null) {
  1929. // open modal with req/action reference
  1930. let btn = document.getElementById("confirm-req-btn");
  1931. btn.setAttribute('data-request', req);
  1932. btn.setAttribute('data-params', params ? JSON.stringify(params) : '{}');
  1933. if(details) {
  1934. document.querySelector("#confirmable-modal p").innerText = details;
  1935. }
  1936. return;
  1937. },
  1938. accept: function () {
  1939. let btn = document.getElementById("confirm-req-btn");
  1940. let req = { type: '', params: {}};
  1941. req.type = btn.getAttribute('data-request');
  1942. req.params = JSON.parse(btn.getAttribute('data-params'));
  1943. switch(req.type) {
  1944. case 'removeAllPromos':
  1945. window.removeAllPromos();
  1946. break;
  1947. case 'forceStopFaucet':
  1948. window.forceStopFaucet();
  1949. break;
  1950. default:
  1951. break;
  1952. }
  1953. }
  1954. }
  1955. window.removeAllPromos = function removeAllPromos() {
  1956. var promoCode = document.getElementById("promo-code-new");
  1957. var promoObject = { action: "REMOVEALLPROMOS" };
  1958. promoCode.innerHTML =JSON.stringify(promoObject);
  1959. toastr["info"]("This could take around a minute", "Removing all promo codes");
  1960. };
  1961. window.forceStopFaucet = function removeAllPromos() {
  1962. console.log('stopping current');
  1963. var promoCode = document.getElementById("promo-code-new");
  1964. var promoObject = { action: "FORCESTOPFAUCET" };
  1965. promoCode.innerHTML =JSON.stringify(promoObject);
  1966. toastr["info"]("Please wait for reload...", "Trying to stop");
  1967. };
  1968. window.openStatsChart = function openStatsChart() {
  1969. if(myBarChart) { myBarChart.destroy(); }
  1970. let statsFragment = document.getElementById("stats-fragment");
  1971. if (statsFragment.style.display === "block") { statsFragment.style.display = "none"; document.getElementById("stats-button").innerText = "Lucky Number Stats"; } else {
  1972. statsFragment.style.display = "block"; document.getElementById("stats-button").innerText = "Close Stats";
  1973. var canvas = document.getElementById("barChart");
  1974. var ctx = canvas.getContext("2d");
  1975. var dataSpan = document.getElementById("rolls-span");
  1976. var data = {
  1977. labels: ["0000-9885", "9886-9985", "9986-9993", "9994-9997", "9998-9999", "10000"],
  1978. datasets: [ { fill: false, backgroundColor: [ "#990000", "#660066", "#000099", "#ff8000", "#ffff00", "#00ff00"],
  1979. data: dataSpan.innerText.split(",") } ] };
  1980. var options = { plugins: { legend: { display: false } }, title: { display: true, text: "Rolled Numbers", position: "top" }, rotation: -0.3 * Math.PI };
  1981. myBarChart = new Chart(ctx, { type: "doughnut", data: data, options: options });
  1982. }
  1983. };
  1984. window.shortlinkAlert = {
  1985. load: function(id, destination) {
  1986. let hideShortlinkAlerts = localStorage.getItem("hideShortlinkAlerts");
  1987. hideShortlinkAlerts = hideShortlinkAlerts ? JSON.parse(hideShortlinkAlerts) : false;
  1988. if (hideShortlinkAlerts) {
  1989. //do alert action without warning (go to SL)
  1990. } else {
  1991. document.getElementById(id).classList.remove("d-none");
  1992. }
  1993. },
  1994. save: function () {
  1995. localStorage.setItem("hideShortlinkAlerts", JSON.stringify(document.getElementById("hideShortlinkAlerts").checked));
  1996. // go to SL
  1997. window.open("https://example.com", "_blank");
  1998. }
  1999. }
  2000. window.hiddenSites = {
  2001. load: function () {
  2002. let hsi = localStorage.getItem("hiddenSiteIds");
  2003. return hsi ? JSON.parse(hsi) : [];
  2004. },
  2005. save: function (hsi) {
  2006. if (hsi) {
  2007. localStorage.setItem("hiddenSiteIds", JSON.stringify(hsi));
  2008. } else {
  2009. localStorage.removeItem("hiddenSiteIds");
  2010. }
  2011. },
  2012. add: function (siteId) {
  2013. let hsi = hiddenSites.load();
  2014. hsi.push(siteId);
  2015. hiddenSites.save(hsi);
  2016. },
  2017. removeAll: function () {
  2018. hiddenSites.save(null);
  2019. }
  2020. };
  2021. window.showHidden = function showHidden() {
  2022. document.querySelectorAll("#schedule-table tr.d-none").forEach(x => x.classList.toggle('d-none'));
  2023. document.querySelectorAll(".fake-row").forEach(x => x.parentElement.removeChild(x));
  2024. document.querySelector('#unhide-btn').classList.add("d-none");
  2025. hiddenSites.removeAll();
  2026. };
  2027. window.hideRow = function hideRow(siteId) {
  2028. let row = document.querySelector("#schedule-table tr[data-id='" + siteId + "']");
  2029. if (row) {
  2030. row.classList.toggle("d-none");
  2031. if (row.classList.contains("d-none")) {
  2032. var fakeRow = document.createElement('tr');
  2033. fakeRow.setAttribute("class", "fake-row");
  2034. row.insertAdjacentElement('afterend', fakeRow);
  2035. hiddenSites.add(siteId);
  2036. document.querySelector('#unhide-btn').classList.remove("d-none");
  2037. }
  2038. }
  2039. };
  2040. }
  2041. };
  2042. let logLines = ['', '', '', '', ''];
  2043. function init(cfFaucets) {
  2044. appendCSS();
  2045. appendJavaScript();
  2046. appendHtml();
  2047. $('#promo-daily').bootstrapSwitch();
  2048. createPromoTable(cfFaucets);
  2049. try {
  2050. document.querySelector('.page-title h1').innerHTML = 'Auto Claim';
  2051. } catch (err) {}
  2052. };
  2053. function appendCSS() {
  2054. let css = document.createElement('style');
  2055. css.innerHTML = `
  2056. td.em-input {
  2057. padding-top: 0;
  2058. padding-bottom: 0;
  2059. }
  2060. `;
  2061. document.head.appendChild(css);
  2062. };
  2063. function appendJavaScript() {
  2064. addJS_Node (null, null, injectables.managerJs);
  2065. };
  2066. function addCardHtml(obj) {
  2067. return `<div class="card m-1"><div class="card-header">${obj.header}</div><div class="card-body px-4">${obj.body}</div></div>`;
  2068. };
  2069. function addSliderHtml(propName, propValue, text) {
  2070. return `<label class="switch"><input type="checkbox" ${propName}="${propValue}" data-original="1"><span class="slider round"></span></label> ${text}`;
  2071. };
  2072. function addRandomBetween(propSelect, propMin, propMax) {
  2073. return `<table><tr><td>
  2074. <select class="form-control" ${propSelect.name}="${propSelect.value}">
  2075. <option value="0">Random between...</option><option value="15">15 minutes</option><option value="30">30 minutes</option><option value="35">35 minutes</option><option value="45">45 minutes</option><option value="65">65 minutes</option><option value="90">90 minutes</option><option value="120">120 minutes</option>
  2076. </select></td>
  2077. <td><input type="number" data-original="" ${propMin.name}="${propMin.value}" min="1" value="15" step="5" class="form-control"></td><td>and</td><td><input type="number" data-original="" ${propMax.name}="${propMax.value}" value="65" step="5" class="form-control"></td><td>minutes</td></tr></table>`;
  2078. }
  2079. function appendHtml() {
  2080. let html ='';
  2081. let cardBody ='';
  2082. html += '<div class="modal fade" id="confirmable-modal" tabindex="-1" role="dialog" aria-hidden="true">';
  2083. html += '<div class="modal-dialog modal-sm modal-dialog-centered"><div class="modal-content">';
  2084. html += '<div class="modal-header"><h4 class="modal-title">Are you sure?</h4><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button></div>';
  2085. html += '<div class="modal-body"><p></p></div>';
  2086. html += '<div class="modal-footer justify-content-between"><button type="button" class="btn btn-default" data-dismiss="modal">No</button>';
  2087. html += '<button type="button" class="btn btn-primary" data-dismiss="modal" id="confirm-req-btn" onclick="confirmable.accept()">Yes</button></div>';
  2088. html += '</div></div>';
  2089. html += '</div>';
  2090. html += '<div class="modal fade" id="modal-dlg" tabindex="-1" role="dialog" data-backdrop="static" aria-hidden="true">';
  2091. html += ' <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable" role="document">';
  2092. // MODAL CONTENTS
  2093. //[Loading]
  2094. 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>';
  2095. //Error report
  2096. html += ' <div class="modal-content bg-beige d-none" id="modal-ereport">';
  2097. html += ' <div class="modal-header"><h5 class="modal-title">Submit an Error</h5></div>';
  2098. html += ' <div class="modal-body">';
  2099. html += ' <div class="alert alert-danger">Don\'t send private information as data might be publicly access.</div>';
  2100. html += ' <textarea rows="4" id="log-message" class="form-control" placeholder="PLEASE do not send logs without describing here the issue you are facing..."></textarea>';
  2101. html += ' <label for="log-textarea">Log</label>';
  2102. html += ' <textarea rows="10" id="log-textarea" class="form-control"></textarea>';
  2103. html += ' </div>';
  2104. 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>';
  2105. 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>';
  2106. html += ' </div>';
  2107. //Wallet
  2108. html += ' <div class="modal-content bg-beige d-none" id="modal-wallet">';
  2109. html += ' <div class="modal-header"><h5 class="modal-title">Your Addresses</h5></div>';
  2110. html += ' <div class="modal-body">';
  2111. html += ' <div><table class="table table-striped" id="wallet-table">';
  2112. html += ' <thead><tr><th class="">Name</th><th class="">Address</th></tr></thead>';
  2113. html += ' <tbody class="overflow-auto" id="wallet-table-body"></tbody></table><textarea rows="14" id="wallet-json" class="d-none w-100"></textarea>';
  2114. html += ' </div>';
  2115. html += ' </div>';
  2116. html += '<div class="modal-footer">';
  2117. html += '<div class="footer-json d-none">';
  2118. html += '<a class="btn m-2 anchor btn-outline-danger align-middle" onclick="editWallet.toggleJson(\'cancel\')"><i class="fa fa-times-circle"></i> Cancel</a>';
  2119. html += '<a class="btn m-2 anchor btn-outline-primary align-middle" onclick="editWallet.toggleJson()"><i class="fa fa-edit"></i> Confirm</a></div>';
  2120. html += '<div class="footer-table"><a class="btn m-2 anchor btn-outline-primary align-middle" onclick="editWallet.toggleJson()"><i class="fa fa-edit"></i> Edit as JSON</a>';
  2121. html += '<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>';
  2122. 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></div>';
  2123. html += ' </div>';
  2124. //Info
  2125. html += ' <div class="modal-content bg-beige d-none" id="modal-info">';
  2126. html += ' <div class="modal-header"><h5 class="modal-title">Info</h5></div>';
  2127. html += ' <div class="modal-body">';
  2128. html += '<ul>';
  2129. html += '<li>Almost all sites in the list require an external hCaptcha solver, you can find one in our <a href="https://discord.gg/23s9fDgHqe" target="_blank">discord</a>.</li>';
  2130. html += '<li>Stormgain requires a GeeTest solver. You can use <a href="https://greasyfork.org/en/scripts/444560" target="_blank">this script</a> to solve the captchas through 2Captcha API service.</li>';
  2131. html += '<li>You can set default configurations at Settings</li>';
  2132. html += '<li>You can override configurations for a specific site using the edit (<i class="fa fa-edit"></i>) buttons</li>';
  2133. html += '<li>Some sites might only work if the tab running it is on focus</li>';
  2134. html += '<li>When enabling a new site, try it first with the tab on focus, to detect potential issues</li>';
  2135. html += '<li>You can enable the log in Settings to detect processing problems</li>';
  2136. html += '</ul>';
  2137. html += ' </div>';
  2138. html += '<div class="modal-footer">';
  2139. html += '<a class="btn m-2 anchor btn-outline-warning align-middle" data-dismiss="modal"><i class="fa fa-edit"></i> Close</a></div>';
  2140. html += ' </div>';
  2141. //Alert Msg
  2142. html += ' <div class="modal-content bg-beige d-none" id="modal-slAlert">';
  2143. html += ' <div class="modal-header"><h5 class="modal-title">Attention</h5></div>';
  2144. html += ' <div class="modal-body">';
  2145. html += ' <div class="alert alert-warning">You will be redirected to a shortlink, and after completing it the new Twitter Daily Promo Code will be added to your table.<br>';
  2146. html += 'This is an optional contribution. You can still get the code the old fashion way.</div>';
  2147. html += addSliderHtml('id', 'hideShortlinkAlerts', `Stop warning me before a shortlink`);
  2148. html += ' </div>';
  2149. html += '<div class="modal-footer"><a class="btn m-2 anchor btn-outline-danger align-middle" onclick="modalCancel(\'slAlert\')" data-dismiss="modal"><i class="fa fa-times-circle"></i> Cancel</a>';
  2150. html += '<a class="btn m-2 anchor btn-outline-success align-middle" onclick="modalSave(\'slAlert\')" data-dismiss="modal"><i class="fa fa-external-link-alt"></i> Lets Go!</a></div>';
  2151. html += ' </div>';
  2152. //Edit Site / single faucet
  2153. html += ' <div class="modal-content bg-beige d-none" id="modal-site">';
  2154. html += ' <div class="modal-header"><h5 class="modal-title">Edit <span id="faucet-name" data-id=""></span> Configuration</h5></div>';
  2155. html += ' <div class="modal-body">';
  2156. html += ' <div class="alert alert-warning">Override Settings for the selected faucet.<br>Faucet-specific configurations will be moved here soon.</div>';
  2157. html += ' <div class="row">';
  2158. html += ' <div class="col-md-12 col-sm-12">';
  2159. html += addCardHtml({
  2160. header: addSliderHtml('data-site-prop', 'defaults.workInBackground.override', 'Override Work Mode'),
  2161. body: addSliderHtml('data-site-prop', 'defaults.workInBackground', 'Open tab in background')
  2162. });
  2163. html += addCardHtml({
  2164. header: addSliderHtml('data-site-prop', 'defaults.nextRun.override', 'Override Next Run'),
  2165. body: `<div>${addSliderHtml('data-site-prop', 'defaults.nextRun.useCountdown', 'Use faucet countdown when possible')}</div>` +
  2166. `<label class="control-label">Otherwise wait:</label>` +
  2167. addRandomBetween({ name: 'data-site-prop', value: 'defaults.nextRun' }, { name: 'data-site-prop', value: 'defaults.nextRun.min' }, { name: 'data-site-prop', value: 'defaults.nextRun.max' })
  2168. });
  2169. html += addCardHtml({
  2170. header: addSliderHtml('data-site-prop', 'defaults.sleepMode.override', 'Override Sleep Mode'),
  2171. body: addSliderHtml('data-site-prop', 'defaults.sleepMode', 'Sleep mode') +
  2172. `<table><tr><td>Don't claim between </td><td><input type="time" data-original="" data-site-prop="defaults.sleepMode.min" class="form-control"></td><td>and</td>
  2173. <td><input type="time" data-original="" data-site-prop="defaults.sleepMode.max" class="form-control"></td></tr></table>`
  2174. });
  2175. html += ' <div class="card m-1"><div class="card-header">Timeout</div>';
  2176. html += ' <div class="card-body px-4">';
  2177. html += addCardHtml({
  2178. header: addSliderHtml('data-site-prop', 'defaults.timeout.override', 'Override Timeout'),
  2179. body: `<table><tr><td>After</td><td><input type="number" data-original="" data-site-prop="defaults.timeout" min="2" value="5" step="1" class="form-control"></td><td>minutes</td></tr></table>`
  2180. });
  2181. html += addCardHtml({
  2182. header: addSliderHtml('data-site-prop', 'defaults.postponeMinutes.override', 'Override Postpone'),
  2183. body: `<label class="control-label">After timeout/error, postpone for:</label>` +
  2184. addRandomBetween({ name: 'data-site-prop', value: 'defaults.postponeMinutes' }, { name: 'data-site-prop', value: 'defaults.postponeMinutes.min' }, { name: 'data-site-prop', value: 'defaults.postponeMinutes.max' })
  2185. });
  2186. html += ' </div>';
  2187. html += ' </div>';
  2188. html += ' </div>';
  2189. html += ' </div>';
  2190. html += ' </div>';
  2191. html += '<div class="modal-footer"><a class="btn m-2 anchor btn-outline-danger align-middle" onclick="modalCancel(\'site\')" data-dismiss="modal"><i class="fa fa-times-circle"></i> Cancel</a>';
  2192. html += '<a class="btn m-2 anchor btn-outline-success align-middle" onclick="modalSave(\'site\')" data-dismiss="modal"><i class="fa fa-check-circle"></i> Save</a></div>';
  2193. html += ' </div>';
  2194. //Config
  2195. html += '<div class="modal-content bg-beige d-none" id="modal-config">';
  2196. html += ' <div class="modal-header"><h5 class="modal-title">Settings</h5></div>';
  2197. html += ' <div class="modal-body">';
  2198. html += ' <div class="alert alert-danger alert-dismissible fade show" id="alert-settings-01">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">&times;</span></button></div>';
  2199. html += ' <div class="alert alert-danger alert-dismissible fade show" id="alert-settings-02">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">&times;</span></button></div>';
  2200. html += ' <div class="row">';
  2201. html += ' <div class="col-md-12 col-sm-12">';
  2202. html += ' <div class="card card-info m-1"><div class="card-header">Defaults<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-minus"></i></button></div></div>';
  2203. html += ' <div class="card-body px-4">';
  2204. html += `<div>${addSliderHtml('data-prop', 'defaults.workInBackground', 'Open tabs in background')}</div>`;
  2205. html += `<div>${addSliderHtml('data-prop', 'defaults.extraInterval', 'Use extra timer to detect ad redirects faster')}</div>`;
  2206. html += addCardHtml({
  2207. header: 'Next Run',
  2208. body: `<div>${addSliderHtml('data-prop', 'defaults.nextRun.useCountdown', 'Use faucet countdown when possible')}</div>` +
  2209. `<label class="control-label">Otherwise wait:</label>` +
  2210. addRandomBetween({ name: 'data-prop', value: 'defaults.nextRun' }, { name: 'data-prop', value: 'defaults.nextRun.min' }, { name: 'data-prop', value: 'defaults.nextRun.max' })
  2211. });
  2212. html += addCardHtml({
  2213. header: 'Timeout',
  2214. body: `<table><tr><td>After</td><td><input type="number" data-original="" data-prop="defaults.timeout" min="2" value="5" step="1" class="form-control"></td><td>minutes</td></tr></table>` +
  2215. `<label class="control-label">After timeout/error, postpone for:</label>` +
  2216. addRandomBetween({ name: 'data-prop', value: 'defaults.postponeMinutes' }, { name: 'data-prop', value: 'defaults.postponeMinutes.min' }, { name: 'data-prop', value: 'defaults.postponeMinutes.max' })
  2217. });
  2218. html += addCardHtml({
  2219. header: 'Logging',
  2220. body: `<div>${addSliderHtml('data-prop', 'devlog.enabled', 'Store log (enables the \'Log\' button)')}</div>` +
  2221. `<table><tr><td>Max log size in lines:</td><td><input type="number" data-original="" data-prop="devlog.maxLines" min="100" step="100" class="form-control"></td></tr></table>`
  2222. });
  2223. html += addCardHtml({
  2224. header: addSliderHtml('data-prop', 'defaults.sleepMode', 'Sleep mode'),
  2225. body: `<table><tr><td>Don't claim between </td><td><input type="time" data-original="" data-prop="defaults.sleepMode.min" class="form-control"></td><td>and</td>
  2226. <td><input type="time" data-original="" data-prop="defaults.sleepMode.max" class="form-control"></td></tr></table>`
  2227. });
  2228. html += ' </div></div>';
  2229. html += ' </div>';
  2230. html += ' <div class="col-md-12 col-sm-12">';
  2231. html += ' <div class="card card-info m-1"><div class="card-header">Site Specifics<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-minus"></i></button></div></div>';
  2232. html += ' <div class="card-body px-4">';
  2233. html += ' <div class="card m-1 collapsed-card"><div class="card-header">CryptosFaucets<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2234. html += ' <div class="card-body px-4" style="display: none;">';
  2235. html += ' <div><label class="switch"><input type="checkbox" data-prop="cf.autologin" ><span class="slider round"></span></label> Autologin when neccessary</div>';
  2236. html += ' <select class="form-control" data-prop="cf.credentials.mode">';
  2237. html += ' <option value="1">Use Email and Password</option><option value="2">Filled by 3rd party software/extension</option>';
  2238. html += ' </select>';
  2239. html += ' <label class="control-label">E-Mail</label>';
  2240. html += ' <input maxlength="200" type="text" data-prop="cf.credentials.email" required="required" class="form-control" placeholder="Email address..."/>';
  2241. html += ' <label class="control-label">Password</label>';
  2242. html += ' <input maxlength="200" type="password" data-prop="cf.credentials.password" required="required" class="form-control" placeholder="Password..."/>';
  2243. html += ' <label class="control-label">Hours to wait If IP is banned:</label>';
  2244. html += ' <select class="form-control" data-prop="cf.sleepHoursIfIpBan">';
  2245. 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>';
  2246. html += ' </select>';
  2247. html += ' </div></div>';
  2248. html += ' <div class="card m-1 collapsed-card"><div class="card-header">FPig<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2249. html += ' <div class="card-body px-4" style="display: none;">';
  2250. html += ' <label class="control-label">Login Mode</label>';
  2251. html += ' <select class="form-control" data-prop="fpb.credentials.mode">';
  2252. html += ' <option value="1">Use Username and Password</option><option value="2">Filled by 3rd party software/extension</option>';
  2253. html += ' </select>';
  2254. html += ' <label class="control-label">E-Mail</label>';
  2255. html += ' <input maxlength="200" type="text" data-prop="fpb.credentials.username" required="required" class="form-control" placeholder="Email address..."/>';
  2256. html += ' <label class="control-label">Password</label>';
  2257. html += ' <input maxlength="200" type="password" data-prop="fpb.credentials.password" required="required" class="form-control" placeholder="Password..."/>';
  2258. html += ' </div></div>';
  2259. html += ' <div class="card m-1 collapsed-card"><div class="card-header">FreeBCH<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2260. html += ' <div class="card-body px-4" style="display: none;">';
  2261. html += ' <label class="control-label">Login Mode</label>';
  2262. html += ' <select class="form-control" data-prop="fbch.credentials.mode">';
  2263. html += ' <option value="1">Use Username and Password</option><option value="2">Filled by 3rd party software/extension</option>';
  2264. html += ' </select>';
  2265. html += ' <label class="control-label">E-Mail</label>';
  2266. html += ' <input maxlength="200" type="text" data-prop="fbch.credentials.username" required="required" class="form-control" placeholder="Email address..."/>';
  2267. html += ' <label class="control-label">Password</label>';
  2268. html += ' <input maxlength="200" type="password" data-prop="fbch.credentials.password" required="required" class="form-control" placeholder="Password..."/>';
  2269. html += ' </div></div>';
  2270. html += ' <div class="card m-1 collapsed-card"><div class="card-header">JTFey<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2271. html += ' <div class="card-body px-4" style="display: none;">';
  2272. html += ' <label class="control-label">Login Mode</label>';
  2273. html += ' <select class="form-control" data-prop="jtfey.credentials.mode">';
  2274. html += ' <option value="1">Use Username and Password</option><option value="2">Filled by 3rd party software/extension</option>';
  2275. html += ' </select>';
  2276. html += ' <label class="control-label">E-Mail</label>';
  2277. html += ' <input maxlength="200" type="text" data-prop="jtfey.credentials.username" required="required" class="form-control" placeholder="Email address..."/>';
  2278. html += ' <label class="control-label">Password</label>';
  2279. html += ' <input maxlength="200" type="password" data-prop="jtfey.credentials.password" required="required" class="form-control" placeholder="Password..."/>';
  2280. html += ' </div></div>';
  2281. html += ' <div class="card m-1 collapsed-card"><div class="card-header">FaucetPay PTC<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2282. html += ' <div class="card-body px-4" style="display: none;">';
  2283. html += ' <label class="control-label">Max duration per run:</label>';
  2284. html += ' <select class="form-control" data-prop="fp.maxTimeInMinutes">';
  2285. 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>';
  2286. html += ' </select>';
  2287. html += ' </div></div>';
  2288. html += ' <div class="card m-1 collapsed-card"><div class="card-header">BestChange<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2289. html += ' <div class="card-body px-4" style="display: none;">';
  2290. html += ' <label class="control-label">BTC Address:</label>';
  2291. html += ' <select class="form-control" data-prop="bestchange.address">';
  2292. html += ' <option value="101">Faucet Pay BTC</option><option value="1">BTC Alt Address</option>';
  2293. html += ' </select>';
  2294. html += ' </div></div>';
  2295. html += ' <div class="card m-1 collapsed-card"><div class="card-header">Bagi/Keran<div class="card-tools"><button type="button" class="btn btn-white btn-sm" data-card-widget="collapse" title="Collapse"><i class="fas fa-plus"></i></button></div></div>';
  2296. html += ' <div class="card-body px-4" style="display: none;">';
  2297. html += ' <label class="control-label">Auto withdraw:</label>';
  2298. html += ' <select class="form-control" data-prop="bk.withdrawMode">';
  2299. html += ' <option value="0">Disabled</option><option value="1">Once every X hours</option><option value="2">After each successful claim</option>';
  2300. html += ' </select>';
  2301. html += ' <label class="control-label">Hours (X) between withdraws:</label>';
  2302. html += ' <select class="form-control" data-prop="bk.hoursBetweenWithdraws">';
  2303. 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>';
  2304. html += ' </select>';
  2305. html += ' <label class="control-label">Time to wait If IP is restricted:</label>';
  2306. html += ' <select class="form-control" data-prop="bk.sleepMinutesIfIpBan">';
  2307. 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>';
  2308. html += ' </select>';
  2309. html += ' </div></div>';
  2310. html += ' </div></div>';
  2311. html += ' </div>';
  2312. html += ' </div>';
  2313. html += '</div>';
  2314. 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>';
  2315. 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>';
  2316. html += ' </div>';
  2317. //END OF MODAL CONTENTS
  2318. html += '</div>';
  2319. html += '</div>';
  2320. html += '<div style="width:100%; padding-left: 1em;" id="console-log"><b>Loading...</b></div>';
  2321. html += '<section id="table-struct" class="fragment "><div class="container-fluid "><div class="py-1 "><div class="row mx-0 justify-content-center">';
  2322. if (shared.getConfig()['devlog.enabled']) {
  2323. html += '<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> Log</a>';
  2324. }
  2325. html += '<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> Settings</a>';
  2326. html += '<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>';
  2327. html += '<a class="btn m-2 anchor btn-outline-primary align-middle" data-toggle="modal" data-target="#modal-dlg" onclick="loadDlg(\'modal-info\')"><i class="fa fa-info"></i> Info</a>';
  2328. html += '<a class="btn m-2 anchor btn-outline-danger align-middle" data-toggle="modal" data-target="#confirmable-modal" onclick="confirmable.open(\'forceStopFaucet\', \'Running faucet will be disabled and the manager will reload.\')"><i class="fa fa-stop-circle"></i> Force Stop</a>';
  2329. // html += '<a class="btn m-2 anchor btn-outline-primary align-middle" data-toggle="modal" data-target="#modal-dlg" onclick="loadDlg(\'modal-slAlert\')"><i class="fa fa-ad"></i> New CF Promo Code</a>';
  2330. html += '</div>';
  2331. html += '<div class="card"><div class="card-header"><h3 class="card-title font-weight-bold">Schedule</h3>';
  2332. html += '<div class="card-tools">';
  2333. html += '<button type="button" class="btn btn-tool-colorless btn-outline-success em-only d-none mx-1" onclick="editListSave()"><i class="fa fa-check-circle"></i> Save</button>';
  2334. html += '<button type="button" class="btn btn-tool-colorless btn-outline-danger em-only d-none mx-1" onclick="editListCancel()"><i class="fa fa-times-circle"></i> Cancel</button>';
  2335. html += `<button type="button" class="btn btn-tool-colorless btn-outline-primary mx-1 em-hide align-middle${localStorage.getItem("hiddenSiteIds") ? '' : ' d-none'}" id="unhide-btn" onclick="showHidden()"><i class="fa fa-eye"></i> Show Hidden</button>`;
  2336. html += '<button type="button" class="btn btn-tool-colorless btn-outline-primary mx-1 em-hide" onclick="editList()"><i class="fa fa-edit"></i> Edit</button>';
  2337. html += '<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>';
  2338. html += '<button type="button" class="btn btn-tool mx-1" data-card-widget="maximize"><i class="fas fa-expand"></i></button>';
  2339. html += '</div></div>';
  2340. html += '<div class="card-body table-responsive p-0" style="height: 400px;" id="schedule-container">';
  2341. html += '</div></div>';
  2342. html += '</div>';
  2343. html += '<span id="update-data" style="display:none;"></span></section>';
  2344. html += '<section id="table-struct-promo" class="fragment "><div class="container-fluid "><div class="py-1 ">';
  2345. html += '<div class="card"><div class="card-header"><h3 class="card-title font-weight-bold">Promo Codes</h3><span id="promo-code-new" style="display:none;"></span>';
  2346. html += '<div class="card-tools">';
  2347. html += '<div class="input-group input-group-sm btn-tool">';
  2348. html += '<input id="promo-text-input" type="text" name="table_search" class="form-control float-right" list="promoCode_list" placeholder="CF Promo Code..." style="width:130px;">';
  2349. html += '<input type="checkbox" data-toggle="switch" title="Check if the code can be reused every 24hs" id="promo-daily" data-on-text="Daily" data-off-text="1 Time">';
  2350. html += '<div class="input-group-append"><button type="submit" class="btn btn-default" id="promo-button" onclick="savePromoCode()"><i class="fas fa-plus"></i> Add</button></div>';
  2351. html += '<div class="input-group-append"><button type="submit" class="btn btn-default btn-outline-danger mx-1" data-toggle="modal" data-target="#confirmable-modal" onclick="confirmable.open(\'removeAllPromos\', \'All promo codes will be removed.\')"><i class="fas fa-times-circle"></i> Remove All</button></div>';
  2352. html += '<button type="button" class="btn btn-tool mx-1" data-card-widget="maximize"><i class="fas fa-expand"></i></button></div>';
  2353. html += '<datalist id="promoCode_list">';
  2354. K.CF.ReusableCodeSuggestions.forEach( function(x) { html += '<option>' + x + '</option>' });
  2355. html += '</datalist>';
  2356. html += '</div>';
  2357. html += '</div>';
  2358. html += '<div class="card-body table-responsive p-0" id="promo-container">';
  2359. html += '</div></div>';
  2360. html +='</div></div></section>';
  2361. html += '<section class="fragment"><div class="container-fluid ">';
  2362. 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>';
  2363. html +='<div class="py-1" id="stats-fragment" style="display:none;"><div class="row align-items-center text-center justify-content-center">';
  2364. html += '<div class="col-md-12 col-lg-8"><canvas id="barChart"></canvas><span id="rolls-span" style="display:none;"></span></div></div></div></div></div></section>';
  2365. let wrapper = document.createElement('div');
  2366. wrapper.innerHTML = html.trim();
  2367. let tgt = document.querySelector('div.row.py-3');
  2368. if (tgt) {
  2369. let rowDiv = document.createElement('div');
  2370. rowDiv.innerHTML = '<div class="row py-3 ac-log"><div class="col-12 justify-content-center"><div class="card"><div class="card-body" id="referral-table"></div></div></div></div>';
  2371. tgt.after(rowDiv);
  2372. }
  2373. let target = document.getElementById('referral-table');
  2374. target.parentNode.insertBefore(wrapper, target);
  2375. document.getElementById('schedule-container').appendChild( createScheduleTable() );
  2376. if (document.querySelector('.main-header .navbar-nav.ml-auto')) {
  2377. let discord = document.createElement('li');
  2378. discord.classList.add('nav-item');
  2379. discord.innerHTML = '<a class="btn btn-primary btn-sm m-1" href="https://discord.gg/23s9fDgHqe" target="_blank"><div class="">discord</div></a>';
  2380. document.querySelector('.main-header .navbar-nav.ml-auto').prepend(discord);
  2381. } else {
  2382. let discord = document.createElement('div');
  2383. discord.innerHTML = '<a class="btn m-2 btn-primary" href="https://discord.gg/23s9fDgHqe" target="_blank"><div class="">discord</div></a>';
  2384. document.querySelector('.navbar-nav').prepend(discord);
  2385. }
  2386. };
  2387. function createPromoTable(faucets) {
  2388. let table = document.createElement('table');
  2389. let inner = '';
  2390. table.classList.add('table', 'table-striped');
  2391. table.setAttribute('id','promo-table');
  2392. inner += '<caption style="text-align: -webkit-center;">⏳ Pending ✔️ Accepted 🕙 Used Before ❌ Invalid code ❗ Unknown error ⚪ No code</caption>';
  2393. inner += '<thead><tr><th class="">Code</th><th class="">Added</th>';
  2394. for (let i = 0, all = faucets.length; i < all; i++) {
  2395. inner += '<th data-faucet-id="' + faucets[i].id + '">' + faucets[i].name + '</th>';
  2396. }
  2397. inner += '</tr></thead><tbody id="promo-table-body"></tbody></table>';
  2398. table.innerHTML = inner
  2399. document.getElementById('promo-container').appendChild( table );
  2400. };
  2401. function createScheduleTable() {
  2402. let table = document.createElement('table');
  2403. let inner;
  2404. table.classList.add('table', 'table-striped', 'table-head-fixed', 'text-nowrap');
  2405. table.setAttribute('id','schedule-table');
  2406. inner = '<thead><tr>';
  2407. inner += '<th scope="col" class="edit-status d-none em-only" style="">Active</th><th class="">Next Roll</th><th class=""></th><th class="">Name</th><th class="">Last Claim</th>';
  2408. inner += '<th class="">Aggregate</th><th class="">Balance</th><th class="" id="converted-balance-col">FIAT</th>';
  2409. inner += '<th scope="col" class="">Msgs</th><th scope="col" class="em-hide" style="">Actions</th></tr></thead><tbody id="schedule-table-body"></tbody>';
  2410. table.innerHTML = inner;
  2411. return table;
  2412. };
  2413. function loadScheduleTable(data) {
  2414. let hsi = localStorage.getItem("hiddenSiteIds");
  2415. hsi = hsi ? JSON.parse(hsi) : [];
  2416. let tableBody = '';
  2417. for(let i=0, all = data.length; i < all; i++) {
  2418. if(hsi.indexOf(data[i].id) > -1) {
  2419. tableBody += '<tr class="fake-row d-none"></tr>'; // nth background styling workaround
  2420. }
  2421. tableBody += `<tr class="align-middle${hsi.indexOf(data[i].id) > -1 ? ' d-none' : ''}" data-id="${data[i].id}" data-enabled="${(data[i].enabled ? '1' : '0')}" data-cmc="${data[i].cmc}" data-balance="`;
  2422. if (data[i].balance) {
  2423. if(typeof data[i].balance == 'string') {
  2424. tableBody += data[i].balance.split(' ')[0];
  2425. } else {
  2426. tableBody += data[i].balance.toFixed(8);
  2427. }
  2428. }
  2429. tableBody += '">';
  2430. 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>';
  2431. tableBody +='<td class="align-middle">' + helpers.getPrintableTime(data[i].nextRoll) + '</td>';
  2432. tableBody +='<td class="align-middle text-left">';
  2433. tableBody +='<a class="" title="Visit site" target="_blank" rel="noreferrer" href="' + (new URL(data[i].clId, 'https://criptologico.com/goto/')).href + '"><i class="fa fa-external-link-alt"></i></a> ';
  2434. tableBody += '</td>';
  2435. tableBody +='<td class="align-middle em-input text-left" data-field="displayName">';
  2436. if (data[i].cmc) {
  2437. tableBody +='<div class="input-group">';
  2438. if (data[i].cmc > 0) {
  2439. let cmcLower = helpers.getEnumText(K.CMC, data[i].cmc).toLowerCase();
  2440. tableBody +='<img loading="lazy" src="/static/c-icons/' + cmcLower + '.svg" height="20" alt="' + cmcLower + '">';
  2441. } else {
  2442. tableBody +='<i class="fa fa-question-circle"></i>';
  2443. }
  2444. }
  2445. tableBody += ' <span class="px-1">' + data[i].name + '</span></div></td>';
  2446. tableBody +='<td class="align-middle">' + data[i].lastClaim.toFixed(Number.isInteger(data[i].lastClaim) ? 0 : 8) + '</td>';
  2447. tableBody +='<td class="align-middle">' + data[i].aggregate.toFixed(Number.isInteger(data[i].aggregate) ? 0 : 8) + '</td>';
  2448. tableBody +='<td class="align-middle">';
  2449. if (data[i].balance) {
  2450. if(typeof data[i].balance == 'string') {
  2451. tableBody += data[i].balance.split(' ')[0];
  2452. } else {
  2453. tableBody += data[i].balance.toFixed(8);
  2454. }
  2455. }
  2456. tableBody + '</td>';
  2457. tableBody +='<td class="align-middle fiat-conversion"></td>';
  2458. tableBody +='<td class="align-middle">' + addBadges(data[i].stats) + '</td>';
  2459. tableBody +='<td class="align-middle justify-content-center em-hide">';
  2460. tableBody +='<a class="px-2" title="Run ASAP" href="javascript:updateValues(\'runAsap\', { id: ' + data[i].id + ' })" onclick=""><i class="fa fa-redo"></i></a>';
  2461. tableBody +=`<a class="px-2 ${Object.keys(data[i].params).some( k => k.endsWith('.override') && data[i].params[k] == true ) ? 'text-warning' : ''}" title="Edit..." data-toggle="modal" data-target="#modal-dlg" onclick="loadDlg('modal-site', '${data[i].id}')"><i class="fa fa-edit"></i></a>`;
  2462. tableBody += !data[i].enabled ? `<a class="px-2" title="Hide..." href="javascript:hideRow('${data[i].id}')" onclick=""><i class="fa fa-eye-slash"></i></a>` : ``;
  2463. tableBody +='</td></tr>';
  2464. }
  2465. document.getElementById('schedule-table-body').innerHTML = tableBody;
  2466. location.href = 'javascript:convertToFiat();';
  2467. };
  2468. function addBadges(stats) {
  2469. let consecutiveTimeout = stats.countTimeouts;
  2470. let otherErrors = stats.errors;
  2471. let html = ' ';
  2472. if (consecutiveTimeout) {
  2473. html += `<span class="badge badge-pill badge-warning" title="${consecutiveTimeout} consecutive timeouts">${consecutiveTimeout}</span>`;
  2474. }
  2475. if (otherErrors) {
  2476. html += `<span class="badge badge-pill badge-warning" title="${otherErrors.errorMessage}">${helpers.getEnumText(K.ErrorType, otherErrors.errorType)}</span>`;
  2477. }
  2478. return html;
  2479. }
  2480. function loadPromotionTable(codes) {
  2481. let tableBody = '';
  2482. for(let c=0; c < codes.length; c++) {
  2483. let data = codes[c];
  2484. tableBody += '<tr data-promotion-id="' + data.id + '">';
  2485. tableBody += '<td class="align-middle text-left ' + (data.repeatDaily ? 'text-warning' : '') + '">';
  2486. 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> ';
  2487. tableBody += '<span title="' + (data.repeatDaily ? 'Reusable Code' : 'One-time-only Code') + '">' + data.code + '</span></td>';
  2488. tableBody +='<td class="align-middle" title="' + (data.repeatDaily ? 'Reusable Code' : 'One-time-only Code') + '">' + helpers.getPrintableDateTime(data.added) + '</td>';
  2489. for(let i=0, all = data.statusPerFaucet.length; i < all; i++) {
  2490. tableBody +='<td class="align-middle" title="Runned @' + helpers.getPrintableDateTime(data.statusPerFaucet[i].execTimeStamp) + '">' + helpers.getEmojiForPromoStatus(data.statusPerFaucet[i].status ?? 0) + '</td>';
  2491. }
  2492. tableBody +='</tr>';
  2493. }
  2494. document.getElementById('promo-table-body').innerHTML = tableBody;
  2495. };
  2496. function loadWalletTable(data) {
  2497. let tableBody = '';
  2498. for(let i=0, all = data.length; i < all; i++) {
  2499. tableBody += '<tr class="align-middle" data-id="'+ data[i].id + '">';
  2500. tableBody += '<td class="align-middle">' + data[i].name + '</td>';
  2501. tableBody += '<td class="align-middle em-input"><input type="text" class="w-100" onfocus="this.select();" data-field="address" data-original="' + data[i].address + '" value="' + data[i].address + '"></td>';
  2502. tableBody += '</tr>';
  2503. }
  2504. document.getElementById('wallet-table-body').innerHTML = tableBody;
  2505. };
  2506. function loadConfigData(data) {
  2507. for (const prop in data) {
  2508. let element = document.querySelector('[data-prop="' + prop + '"]');
  2509. if(element) {
  2510. if(element.type == 'select-one' || element.type == 'text' || element.type == 'password' || element.type == 'number' || element.type == 'time') {
  2511. element.dataset.original = data[prop];
  2512. element.value = data[prop];
  2513. } else if (element.type == 'checkbox') {
  2514. element.dataset.original = (data[prop] ? "1" : "0");
  2515. element.checked = data[prop];
  2516. }
  2517. }
  2518. }
  2519. let elCredentialsAutologin = document.querySelector('[data-prop="cf.autologin"]');
  2520. let elCredentialsMode = document.querySelector('[data-prop="cf.credentials.mode"]');
  2521. let elCredentialsEmail = document.querySelector('[data-prop="cf.credentials.email"]');
  2522. let elCredentialsPassword = document.querySelector('[data-prop="cf.credentials.password"]');
  2523. let elWithdrawMode = document.querySelector('[data-prop="bk.withdrawMode"]');
  2524. let elHoursBetweenWithdraws = document.querySelector('[data-prop="bk.hoursBetweenWithdraws"]');
  2525. let elDevlogEnabled = document.querySelector('[data-prop="devlog.enabled"]');
  2526. let elDevlogMaxLines = document.querySelector('[data-prop="devlog.maxLines"]');
  2527. let elFpigCredentialsMode = document.querySelector('[data-prop="fpb.credentials.mode"]');
  2528. let elFpigCredentialsUsername = document.querySelector('[data-prop="fpb.credentials.username"]');
  2529. let elFpigCredentialsPassword = document.querySelector('[data-prop="fpb.credentials.password"]');
  2530. let elFBchCredentialsMode = document.querySelector('[data-prop="fbch.credentials.mode"]');
  2531. let elFBchCredentialsUsername = document.querySelector('[data-prop="fbch.credentials.username"]');
  2532. let elFBchCredentialsPassword = document.querySelector('[data-prop="fbch.credentials.password"]');
  2533. let elJtfeyCredentialsMode = document.querySelector('[data-prop="jtfey.credentials.mode"]');
  2534. let elJtfeyCredentialsUsername = document.querySelector('[data-prop="jtfey.credentials.username"]');
  2535. let elJtfeyCredentialsPassword = document.querySelector('[data-prop="jtfey.credentials.password"]');
  2536. let elPostpone = document.querySelector('[data-prop="defaults.postponeMinutes"]');
  2537. let elPostponeMin = document.querySelector('[data-prop="defaults.postponeMinutes.min"]');
  2538. let elPostponeMax = document.querySelector('[data-prop="defaults.postponeMinutes.max"]');
  2539. elPostponeMin.disabled = (elPostpone.value > "0");
  2540. elPostponeMax.disabled = (elPostpone.value > "0");
  2541. if (elPostponeMin.disabled && elPostponeMax.disabled) {
  2542. elPostponeMin.value = elPostpone.value;
  2543. elPostponeMax.value = elPostpone.value;
  2544. }
  2545. elPostpone.onchange = function (e) {
  2546. document.querySelector('[data-prop="defaults.postponeMinutes.min"]').disabled = e.target.value > 0;
  2547. document.querySelector('[data-prop="defaults.postponeMinutes.max"]').disabled = e.target.value > 0;
  2548. if (e.target.value > 0) {
  2549. document.querySelector('[data-prop="defaults.postponeMinutes.min"]').value = e.target.value;
  2550. document.querySelector('[data-prop="defaults.postponeMinutes.max"]').value = e.target.value;
  2551. }
  2552. }
  2553. let elNextRun = document.querySelector('[data-prop="defaults.nextRun"]');
  2554. let elNextRunMin = document.querySelector('[data-prop="defaults.nextRun.min"]');
  2555. let elNextRunMax = document.querySelector('[data-prop="defaults.nextRun.max"]');
  2556. let elNextRunUseCountdown = document.querySelector('[data-prop="defaults.nextRun.useCountdown"]');
  2557. elNextRunMin.disabled = (elNextRun.value > "0");
  2558. elNextRunMax.disabled = (elNextRun.value > "0");
  2559. if (elNextRunMin.disabled && elNextRunMax.disabled) {
  2560. elNextRunMin.value = elNextRun.value;
  2561. elNextRunMax.value = elNextRun.value;
  2562. }
  2563. elNextRun.onchange = function (e) {
  2564. document.querySelector('[data-prop="defaults.nextRun.min"]').disabled = e.target.value > 0;
  2565. document.querySelector('[data-prop="defaults.nextRun.max"]').disabled = e.target.value > 0;
  2566. if (e.target.value > 0) {
  2567. document.querySelector('[data-prop="defaults.nextRun.min"]').value = e.target.value;
  2568. document.querySelector('[data-prop="defaults.nextRun.max"]').value = e.target.value;
  2569. }
  2570. }
  2571. let elSleepMode = document.querySelector('[data-prop="defaults.sleepMode"]');
  2572. let elSleepModeMin = document.querySelector('[data-prop="defaults.sleepMode.min"]');
  2573. let elSleepModeMax = document.querySelector('[data-prop="defaults.sleepMode.max"]');
  2574. elSleepModeMin.disabled = !elSleepMode.checked;
  2575. elSleepModeMax.disabled = !elSleepMode.checked;
  2576. elSleepMode.onchange = function (e) {
  2577. document.querySelector('[data-prop="defaults.sleepMode.min"]').disabled = !e.target.checked;
  2578. document.querySelector('[data-prop="defaults.sleepMode.max"]').disabled = !e.target.checked;
  2579. }
  2580. elCredentialsMode.disabled = !elCredentialsAutologin.checked;
  2581. elCredentialsEmail.disabled = ( (!elCredentialsAutologin.checked || elCredentialsMode.value == "2") ? true : false);
  2582. elCredentialsPassword.disabled = ( (!elCredentialsAutologin.checked || elCredentialsMode.value == "2") ? true : false);
  2583. elHoursBetweenWithdraws.disabled = ( (elWithdrawMode.value == "0" || elWithdrawMode.value == "2") ? true : false);
  2584. elCredentialsAutologin.onchange = function (e) {
  2585. document.querySelector('[data-prop="cf.credentials.mode"]').disabled = !e.target.checked;
  2586. if (elCredentialsMode.value == "2") {
  2587. document.querySelector('[data-prop="cf.credentials.email"]').disabled = true;
  2588. document.querySelector('[data-prop="cf.credentials.password"]').disabled = true;
  2589. } else {
  2590. document.querySelector('[data-prop="cf.credentials.email"]').disabled = false;
  2591. document.querySelector('[data-prop="cf.credentials.password"]').disabled = false;
  2592. }
  2593. }
  2594. elCredentialsMode.onchange = function (e) {
  2595. if (e.target.value == "2") {
  2596. document.querySelector('[data-prop="cf.credentials.email"]').disabled = true;
  2597. document.querySelector('[data-prop="cf.credentials.password"]').disabled = true;
  2598. } else {
  2599. document.querySelector('[data-prop="cf.credentials.email"]').disabled = false;
  2600. document.querySelector('[data-prop="cf.credentials.password"]').disabled = false;
  2601. }
  2602. }
  2603. elFpigCredentialsUsername.disabled = ( (elFpigCredentialsMode.value == "2") ? true : false);
  2604. elFpigCredentialsPassword.disabled = ( (elFpigCredentialsMode.value == "2") ? true : false);
  2605. elFpigCredentialsMode.onchange = function (e) {
  2606. if (e.target.value == "2") {
  2607. document.querySelector('[data-prop="fpb.credentials.username"]').disabled = true;
  2608. document.querySelector('[data-prop="fpb.credentials.password"]').disabled = true;
  2609. } else {
  2610. document.querySelector('[data-prop="fpb.credentials.username"]').disabled = false;
  2611. document.querySelector('[data-prop="fpb.credentials.password"]').disabled = false;
  2612. }
  2613. }
  2614. elFBchCredentialsUsername.disabled = ( (elFBchCredentialsMode.value == "2") ? true : false);
  2615. elFBchCredentialsPassword.disabled = ( (elFBchCredentialsMode.value == "2") ? true : false);
  2616. elFBchCredentialsMode.onchange = function (e) {
  2617. if (e.target.value == "2") {
  2618. document.querySelector('[data-prop="fbch.credentials.username"]').disabled = true;
  2619. document.querySelector('[data-prop="fbch.credentials.password"]').disabled = true;
  2620. } else {
  2621. document.querySelector('[data-prop="fbch.credentials.username"]').disabled = false;
  2622. document.querySelector('[data-prop="fbch.credentials.password"]').disabled = false;
  2623. }
  2624. }
  2625. elJtfeyCredentialsUsername.disabled = ( (elJtfeyCredentialsMode.value == "2") ? true : false);
  2626. elJtfeyCredentialsPassword.disabled = ( (elJtfeyCredentialsMode.value == "2") ? true : false);
  2627. elJtfeyCredentialsMode.onchange = function (e) {
  2628. if (e.target.value == "2") {
  2629. document.querySelector('[data-prop="jtfey.credentials.username"]').disabled = true;
  2630. document.querySelector('[data-prop="jtfey.credentials.password"]').disabled = true;
  2631. } else {
  2632. document.querySelector('[data-prop="jtfey.credentials.username"]').disabled = false;
  2633. document.querySelector('[data-prop="jtfey.credentials.password"]').disabled = false;
  2634. }
  2635. }
  2636. elWithdrawMode.onchange = function (e) {
  2637. if (e.target.value == "0" || e.target.value == "2") {
  2638. document.querySelector('[data-prop="bk.hoursBetweenWithdraws"]').disabled = true;
  2639. } else {
  2640. document.querySelector('[data-prop="bk.hoursBetweenWithdraws"]').disabled = false;
  2641. }
  2642. }
  2643. elDevlogMaxLines.disabled = !elDevlogEnabled.checked;
  2644. elDevlogEnabled.onchange = function (e) {
  2645. document.querySelector('[data-prop="devlog.maxLines"]').disabled = !e.target.checked;
  2646. }
  2647. };
  2648. function loadSiteData(site, config) {
  2649. document.querySelector('#faucet-name').innerHTML = site.name;
  2650. document.querySelector('#faucet-name').dataset.id = site.id;
  2651. let data = site.params || {};
  2652. for (const prop in config) {
  2653. let overrideElement = document.querySelector('[data-site-prop="' + prop + '.override"]');
  2654. if (overrideElement) {
  2655. overrideElement.dataset.original = (data[prop + '.override'] ? "1" : "0");
  2656. overrideElement.checked = data[prop + '.override'];
  2657. }
  2658. let element = document.querySelector('[data-site-prop="' + prop + '"]');
  2659. if(element) {
  2660. if(element.type == 'select-one' || element.type == 'text' || element.type == 'password' || element.type == 'number' || element.type == 'time') {
  2661. element.dataset.original = data[prop] ?? config[prop];
  2662. element.value = data[prop] ?? config[prop];
  2663. } else if (element.type == 'checkbox') {
  2664. element.dataset.original = ((data[prop] ?? config[prop]) ? "1" : "0");
  2665. element.checked = data[prop] ?? config[prop];
  2666. }
  2667. element.disabled = true;
  2668. }
  2669. }
  2670. let elWorkInBackgroundOverride = document.querySelector('[data-site-prop="defaults.workInBackground.override"]');
  2671. let elWorkInBackground = document.querySelector('[data-site-prop="defaults.workInBackground"]');
  2672. elWorkInBackground.disabled = !elWorkInBackgroundOverride.checked;
  2673. elWorkInBackgroundOverride.onchange = function (e) {
  2674. document.querySelector('[data-site-prop="defaults.workInBackground"]').disabled = !e.target.checked;
  2675. }
  2676. let elTimeoutOverride = document.querySelector('[data-site-prop="defaults.timeout.override"]');
  2677. let elTimeout = document.querySelector('[data-site-prop="defaults.timeout"]');
  2678. elTimeout.disabled = !elTimeoutOverride.checked;
  2679. elTimeoutOverride.onchange = function (e) {
  2680. document.querySelector('[data-site-prop="defaults.timeout"]').disabled = !e.target.checked;
  2681. }
  2682. let elPostponeOverride = document.querySelector('[data-site-prop="defaults.postponeMinutes.override"]');
  2683. let elPostpone = document.querySelector('[data-site-prop="defaults.postponeMinutes"]');
  2684. let elPostponeMin = document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]');
  2685. let elPostponeMax = document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]');
  2686. elPostpone.disabled = !elPostponeOverride.checked;
  2687. elPostponeMin.disabled = !elPostponeOverride.checked || (elPostpone.value > "0");
  2688. elPostponeMax.disabled = !elPostponeOverride.checked || (elPostpone.value > "0");
  2689. elPostponeOverride.onchange = function (e) {
  2690. let mode = document.querySelector('[data-site-prop="defaults.postponeMinutes"]');
  2691. mode.disabled = !e.target.checked;
  2692. document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]').disabled = !e.target.checked || mode.value > 0;
  2693. document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]').disabled = !e.target.checked || mode.value > 0;
  2694. }
  2695. elPostpone.onchange = function (e) {
  2696. document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]').disabled = e.target.value > 0;
  2697. document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]').disabled = e.target.value > 0;
  2698. if (e.target.value > 0) {
  2699. document.querySelector('[data-site-prop="defaults.postponeMinutes.min"]').value = e.target.value;
  2700. document.querySelector('[data-site-prop="defaults.postponeMinutes.max"]').value = e.target.value;
  2701. }
  2702. }
  2703. let elNextRunOverride = document.querySelector('[data-site-prop="defaults.nextRun.override"]');
  2704. let elNextRun = document.querySelector('[data-site-prop="defaults.nextRun"]');
  2705. let elNextRunMin = document.querySelector('[data-site-prop="defaults.nextRun.min"]');
  2706. let elNextRunMax = document.querySelector('[data-site-prop="defaults.nextRun.max"]');
  2707. let elNextRunUseCountdown = document.querySelector('[data-site-prop="defaults.nextRun.useCountdown"]');
  2708. elNextRun.disabled = !elNextRunOverride.checked;
  2709. elNextRunMin.disabled = !elNextRunOverride.checked || (elNextRun.value > "0");
  2710. elNextRunMax.disabled = !elNextRunOverride.checked || (elNextRun.value > "0");
  2711. elNextRunUseCountdown.disabled = !elNextRunOverride.checked;
  2712. elNextRunOverride.onchange = function (e) {
  2713. let mode = document.querySelector('[data-site-prop="defaults.nextRun"]');
  2714. mode.disabled = !e.target.checked;
  2715. document.querySelector('[data-site-prop="defaults.nextRun.min"]').disabled = !e.target.checked || mode.value > 0;
  2716. document.querySelector('[data-site-prop="defaults.nextRun.max"]').disabled = !e.target.checked || mode.value > 0;
  2717. document.querySelector('[data-site-prop="defaults.nextRun.useCountdown"]').disabled = !e.target.checked;
  2718. }
  2719. elNextRun.onchange = function (e) {
  2720. document.querySelector('[data-site-prop="defaults.nextRun.min"]').disabled = e.target.value > 0;
  2721. document.querySelector('[data-site-prop="defaults.nextRun.max"]').disabled = e.target.value > 0;
  2722. if (e.target.value > 0) {
  2723. document.querySelector('[data-site-prop="defaults.nextRun.min"]').value = e.target.value;
  2724. document.querySelector('[data-site-prop="defaults.nextRun.max"]').value = e.target.value;
  2725. }
  2726. }
  2727. let elSleepOverride = document.querySelector('[data-site-prop="defaults.sleepMode.override"]');
  2728. let elSleep = document.querySelector('[data-site-prop="defaults.sleepMode"]');
  2729. let elSleepMin = document.querySelector('[data-site-prop="defaults.sleepMode.min"]');
  2730. let elSleepMax = document.querySelector('[data-site-prop="defaults.sleepMode.max"]');
  2731. elSleep.disabled = !elSleepOverride.checked;
  2732. // elNextRun.disabled = !elNextRunOverride.checked;
  2733. elSleepMin.disabled = !elSleepOverride.checked || !elSleep.checked;
  2734. elSleepMax.disabled = !elSleepOverride.checked || !elSleep.checked;
  2735. elSleepOverride.onchange = function (e) {
  2736. let mode = document.querySelector('[data-site-prop="defaults.sleepMode"]');
  2737. mode.disabled = !e.target.checked;
  2738. document.querySelector('[data-site-prop="defaults.sleepMode.min"]').disabled = !e.target.checked || !mode.checked;
  2739. document.querySelector('[data-site-prop="defaults.sleepMode.max"]').disabled = !e.target.checked || !mode.checked;
  2740. }
  2741. elSleep.onchange = function (e) {
  2742. document.querySelector('[data-site-prop="defaults.sleepMode.min"]').disabled = !e.target.checked;
  2743. document.querySelector('[data-site-prop="defaults.sleepMode.max"]').disabled = !e.target.checked;
  2744. }
  2745. return;
  2746. };
  2747. function refresh(scheduleData, promotionData, walletData, configData, siteData) {
  2748. if (scheduleData) {
  2749. loadScheduleTable(scheduleData);
  2750. }
  2751. if (promotionData) {
  2752. loadPromotionTable(promotionData);
  2753. }
  2754. if (walletData) {
  2755. loadWalletTable(walletData);
  2756. }
  2757. if (configData) {
  2758. loadConfigData(configData);
  2759. }
  2760. if (siteData) {
  2761. loadSiteData(siteData.site, siteData.config);
  2762. }
  2763. };
  2764. function log(msg, elapsed = false) {
  2765. if(shared.getConfig()['devlog.enabled']) { shared.devlog(msg, elapsed) };
  2766. if(msg) {
  2767. let previous = logLines[0].split('&nbsp')[1];
  2768. if(elapsed && (previous == msg)) {
  2769. logLines[0] = helpers.getPrintableTime() + '&nbsp' + msg + '&nbsp[Elapsed time:&nbsp' + elapsed + '&nbspseconds]';
  2770. } else {
  2771. logLines.pop();
  2772. logLines.unshift(helpers.getPrintableTime() + '&nbsp' + msg);
  2773. }
  2774. document.getElementById('console-log').innerHTML = logLines.join('<br>');
  2775. }
  2776. };
  2777. return {
  2778. init: init,
  2779. refresh: refresh,
  2780. loadPromotionTable: loadPromotionTable,
  2781. log: log
  2782. }
  2783. },
  2784. createCFPromotions: function() {
  2785. let codes = [];
  2786. function PromotionCode(id, code, repeatDaily = false) {
  2787. this.id = id;
  2788. this.code = code;
  2789. this.added = new Date();
  2790. this.statusPerFaucet = [];
  2791. this.repeatDaily = repeatDaily;
  2792. this.lastExecTimeStamp = null;
  2793. };
  2794. function getFaucetStatusInPromo(promo, faucetId) {
  2795. let faucet = promo.statusPerFaucet.find(x => x.id == faucetId);
  2796. if (faucet.status && promo.repeatDaily) {
  2797. //Using 26 hs instead of 24hs, and 2hs gap retry when code is flagged as USEDBEFORE
  2798. if((faucet.status == K.CF.PromoStatus.ACCEPTED && (Date.now() - faucet.execTimeStamp.getTime()) > K.Integers.HS_26_IN_MILLISECONDS)
  2799. || (faucet.status == K.CF.PromoStatus.USEDBEFORE && (Date.now() - faucet.execTimeStamp.getTime()) > K.Integers.HS_2_IN_MILLISECONDS)) {
  2800. faucet.status = K.CF.PromoStatus.PENDING;
  2801. }
  2802. }
  2803. return faucet.status ?? K.CF.PromoStatus.NOCODE;
  2804. };
  2805. function addNew(code, repeatDaily = false) {
  2806. let newPromo = new PromotionCode(codes.length, code, repeatDaily);
  2807. newPromo.statusPerFaucet = manager.getFaucetsForPromotion().map(x => {
  2808. return {
  2809. id: x.id,
  2810. };});
  2811. newPromo.statusPerFaucet.forEach(function (element, idx, arr) {
  2812. arr[idx].status = K.CF.PromoStatus.PENDING;
  2813. arr[idx].execTimeStamp = null;
  2814. });
  2815. codes.push(newPromo);
  2816. codes.sort((a, b) => (a.id < b.id) ? 1 : -1);
  2817. save();
  2818. };
  2819. function getAll() {
  2820. return codes;
  2821. };
  2822. function updateFaucetForCode(code, faucetId, newStatus) {
  2823. let promo = codes.find(x => x.code == code);
  2824. let faucet = promo.statusPerFaucet.find(x => x.id == faucetId);
  2825. if(faucet) {
  2826. faucet.status = newStatus;
  2827. faucet.execTimeStamp = new Date();
  2828. promo.lastExecTimeStamp = faucet.execTimeStamp;
  2829. }
  2830. save();
  2831. };
  2832. function hasPromoAvailable(faucetId) {
  2833. let resp = false;
  2834. codes.forEach(function (promotion, idx, arr) {
  2835. let status = getFaucetStatusInPromo(promotion, faucetId);
  2836. if (status == K.CF.PromoStatus.PENDING) {
  2837. resp = promotion.code;
  2838. return;
  2839. }
  2840. });
  2841. return resp;
  2842. };
  2843. function save() {
  2844. persistence.save('CFPromotions', getAll(), true);
  2845. };
  2846. function load(data) {
  2847. codes = data;
  2848. };
  2849. function removeAll() {
  2850. codes = [];
  2851. save();
  2852. };
  2853. function remove(id, code) {
  2854. let idx = codes.findIndex(x => x.id == id && x.code == code);
  2855. if(idx != -1) {
  2856. codes.splice(idx, 1);
  2857. save();
  2858. }
  2859. return idx;
  2860. };
  2861. return {
  2862. addNew: addNew,
  2863. removeAll: removeAll,
  2864. remove: remove,
  2865. getAll: getAll,
  2866. load: load,
  2867. updateFaucetForCode: updateFaucetForCode,
  2868. hasPromoAvailable: hasPromoAvailable
  2869. }
  2870. },
  2871. createInteractions: function(){
  2872. let randomInteractionLevel = K.RandomInteractionLevel.MEDIUM;
  2873. let maxActions = 0;
  2874. let performedActions = -1;
  2875. let selectableElements;
  2876. let actions = {
  2877. available: [
  2878. function() {
  2879. $('html, body').animate({
  2880. scrollTop: helpers.randomInt(0, $('html, body').get(0).scrollHeight)
  2881. }, {
  2882. complete: setTimeout(interactions.addPerformed, helpers.randomMs(100, 3000)),
  2883. duration: helpers.randomMs(100, 1500)
  2884. });
  2885. },
  2886. function() {
  2887. let element = interactions.selectableElements[helpers.randomInt(0, interactions.selectableElements.length - 1)];
  2888. try {
  2889. if (document.body.createTextRange) {
  2890. const range = document.body.createTextRange();
  2891. range.moveToElementText(element);
  2892. range.select();
  2893. } else if (window.getSelection) {
  2894. const selection = window.getSelection();
  2895. const range = document.createRange();
  2896. range.selectNodeContents(element);
  2897. selection.removeAllRanges();
  2898. selection.addRange(range);
  2899. }
  2900. } catch (err) { }
  2901. interactions.addPerformed();
  2902. }
  2903. ]
  2904. };
  2905. function start(selectableElements) {
  2906. performedActions = 0;
  2907. switch(randomInteractionLevel) {
  2908. case K.RandomInteractionLevel.NONE:
  2909. maxActions = 0;
  2910. break;
  2911. case K.RandomInteractionLevel.LOW:
  2912. maxActions = helpers.randomInt(2, 4);
  2913. break;
  2914. case K.RandomInteractionLevel.MEDIUM:
  2915. maxActions = helpers.randomInt(5, 8);
  2916. break;
  2917. case K.RandomInteractionLevel.HIGH:
  2918. maxActions = helpers.randomInt(12, 16);
  2919. break;
  2920. }
  2921. interactions.selectableElements = selectableElements;
  2922. performActions();
  2923. }
  2924. function performActions() {
  2925. if(performedActions >= maxActions) {
  2926. return;
  2927. }
  2928. let delay = 0;
  2929. for(let i = 0; i < maxActions; i++) {
  2930. delay += helpers.randomMs(350, 1500);
  2931. setTimeout(actions.available[helpers.randomInt(0, actions.available.length - 1)], delay);
  2932. }
  2933. }
  2934. function addPerformed() {
  2935. performedActions++;
  2936. }
  2937. function completed() {
  2938. return (performedActions >= maxActions);
  2939. }
  2940. return {
  2941. start: start,
  2942. completed: completed,
  2943. addPerformed: addPerformed,
  2944. selectableElements: selectableElements
  2945. };
  2946. },
  2947. createSGProcessor: function() {
  2948. let timerSpans;
  2949. function run() {
  2950. if(isLoading()) {
  2951. setTimeout(run, helpers.randomMs(5000, 10000));
  2952. return;
  2953. } else if (hasPopup()) {
  2954. closePopup();
  2955. setTimeout(run, helpers.randomMs(5000, 10000));
  2956. } else {
  2957. if(isMinerActive()) {
  2958. processRunDetails();
  2959. } else {
  2960. // Wait for captcha to be solved
  2961. setTimeout(run, helpers.randomMs(5000, 10000));
  2962. // activateMiner();
  2963. }
  2964. }
  2965. };
  2966. function hasPopup() {
  2967. if (document.querySelector('div.absolute.flex.top-0.right-0.cursor-pointer.p-4.text-white.md-text-gray-1')) {
  2968. return true;
  2969. }
  2970. return false;
  2971. };
  2972. function closePopup() {
  2973. try {
  2974. shared.devlog(`@SG: closing popup`);
  2975. document.querySelector("div.absolute.flex.top-0.right-0.cursor-pointer.p-4.text-white.md-text-gray-1").click();
  2976. document.querySelector('svg.flex.w-8.h-8.fill-current').parentElement.click();
  2977. } catch { shared.devlog(`@SG: error closing popup`); }
  2978. };
  2979. function isLoading() {
  2980. return document.getElementById('loader-logo') ? true : false;
  2981. };
  2982. function isMinerActive() {
  2983. timerSpans = document.querySelector('.font-bold.text-center.text-accent.w-11-12.text-18 span');
  2984. if(timerSpans) {
  2985. shared.devlog(`SG: Miner is active`);
  2986. return true;
  2987. } else {
  2988. shared.devlog(`SG: Miner is inactive`);
  2989. return false;
  2990. }
  2991. return (!!timerSpans);
  2992. };
  2993. function activateMiner() {
  2994. let activateButton = document.querySelector("#region-main button.activate.block.w-full.h-full.mx-auto.p-0.rounded-full.select-none.cursor-pointer.focus-outline-none.border-0.bg-transparent");
  2995. // let activateButton = document.querySelector('.mb-8 .wrapper button');
  2996. if (activateButton) {
  2997. activateButton.click();
  2998. shared.devlog(`SG: Activate miner clicked`);
  2999. setTimeout(run, helpers.randomMs(10000, 20000));
  3000. } else {
  3001. processRunDetails()
  3002. }
  3003. };
  3004. function processRunDetails() {
  3005. let result = {};
  3006. shared.devlog(`SG: @processRunDetails`);
  3007. result.nextRoll = helpers.addMinutes(readCountdown().toString());
  3008. result.balance = readBalance();
  3009. shared.closeWindow(result);
  3010. };
  3011. function readCountdown() {
  3012. shared.devlog(`SG: @readCountdown`);
  3013. let synchronizing = document.querySelector('.text-15.font-bold.text-center.text-accent'); // use
  3014. let mins = 15;
  3015. try {
  3016. let timeLeft = timerSpans.innerText.split(':');
  3017. if (timeLeft[0] == 'Synchronizing') {
  3018. //should retry to load the value
  3019. }
  3020. shared.devlog(`SG Countdown timeLeft spans:`);
  3021. shared.devlog(timeLeft);
  3022. if(timeLeft.length === 3) {
  3023. mins = parseInt(timeLeft[0]) * 60 + parseInt(timeLeft[1]);
  3024. }
  3025. } catch (err) { shared.devlog(`SG Error reading countdown: ${err}`); }
  3026. return mins;
  3027. };
  3028. function readBalance() {
  3029. shared.devlog(`SG: @readBalance`);
  3030. let balance = "";
  3031. try {
  3032. balance = document.querySelector('span.text-accent').innerText + " BTC";
  3033. } catch (err) { }
  3034. return balance;
  3035. };
  3036. return {
  3037. run: run,
  3038. processRunDetails: processRunDetails
  3039. };
  3040. },
  3041. createCFProcessor: function() {
  3042. const NavigationProcess = {
  3043. ROLLING: 1,
  3044. PROCESSING_PROMOTION: 2,
  3045. LOGIN: 3
  3046. };
  3047. let navigationProcess;
  3048. let countdown;
  3049. let rollButton;
  3050. let promotionTag;
  3051. let timeWaiting= 0;
  3052. let loopingForErrors = false;
  3053. function init() {
  3054. let urlType = helpers.cf.getUrlType(window.location.href);
  3055. switch(urlType) {
  3056. case K.CF.UrlType.FREE:
  3057. if(localeConfig.setToEnglish) {
  3058. let refValue = document.querySelectorAll('.nav-item a')[4].innerHTML;
  3059. if (refValue != 'Settings') {
  3060. window.location.href = '/set-language/en';
  3061. }
  3062. }
  3063. addJS_Node (null, null, overrideSelectNativeJS_Functions);
  3064. interactions = objectGenerator.createInteractions();
  3065. run();
  3066. break;
  3067. case K.CF.UrlType.PROMOTION:
  3068. interactions = objectGenerator.createInteractions();
  3069. runPromotion();
  3070. break;
  3071. case K.CF.UrlType.HOME:
  3072. if (shared.getConfig()['cf.autologin']) {
  3073. addJS_Node (null, null, overrideSelectNativeJS_Functions);
  3074. doLogin();
  3075. } else {
  3076. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  3077. }
  3078. break;
  3079. case K.CF.UrlType.CONTACTTWITTER:
  3080. shared.closeWithError(K.ErrorType.IP_BAN, '');
  3081. break;
  3082. default:
  3083. break;
  3084. }
  3085. return;
  3086. }
  3087. function run() {
  3088. navigationProcess = NavigationProcess.ROLLING;
  3089. displayStatusUi();
  3090. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  3091. };
  3092. function doLogin() {
  3093. navigationProcess = NavigationProcess.LOGIN;
  3094. displayStatusUi();
  3095. setTimeout(findLoginForm, helpers.randomMs(2000, 5000));
  3096. };
  3097. function isFullyLoaded() { //Waits 55 seconds max
  3098. if(document.readyState == 'complete' || timeWaiting == -1) {
  3099. document.getElementById('process-status').innerHTML = 'Interacting';
  3100. timeWaiting = 0;
  3101. interact();
  3102. } else {
  3103. timeWaiting = -1;
  3104. document.getElementById('process-status').innerHTML = 'Waiting for document fully loaded';
  3105. setTimeout(isFullyLoaded, helpers.randomMs(15000, 25000));
  3106. }
  3107. };
  3108. function runPromotion() {
  3109. navigationProcess = NavigationProcess.PROCESSING_PROMOTION
  3110. displayStatusUi();
  3111. setTimeout(findPromotionTag, helpers.randomMs(1000, 3000));
  3112. };
  3113. function findCountdownOrRollButton() {
  3114. if( isCountdownVisible() && !isRollButtonVisible() ) {
  3115. timeWaiting = 0;
  3116. processRunDetails();
  3117. } else if ( !isCountdownVisible() && isRollButtonVisible() ) {
  3118. timeWaiting = 0;
  3119. setTimeout(isFullyLoaded, helpers.randomMs(1000, 5000));
  3120. } else if ( isCountdownVisible() && isRollButtonVisible() ) {
  3121. // if countdown 0/-1, try to roll
  3122. try {
  3123. let minLeft = document.querySelector('.minutes .digits').innerText;
  3124. if (minLeft < 1) {
  3125. timeWaiting = 0;
  3126. setTimeout(isFullyLoaded, helpers.randomMs(1000, 5000));
  3127. }
  3128. } catch (err) { shared.devlog(`Error on alt logic of CF roll: ${err}`); }
  3129. } else {
  3130. if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
  3131. shared.closeWithError(K.ErrorType.TIMEOUT, '');
  3132. return;
  3133. }
  3134. timeWaiting += 3000;
  3135. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  3136. }
  3137. };
  3138. function findLoginForm() {
  3139. if ( document.querySelector('div.login-wrapper').isVisible() ) {
  3140. //Other possible error is if recaptcha did not load yet... so maybe wait til the web is fully loaded for low connection issues
  3141. let errElement = document.querySelector('.login-wrapper .error');
  3142. if( errElement && errElement.innerHTML != '') {
  3143. let errorMessage = errElement.innerText;
  3144. shared.closeWithError(K.ErrorType.LOGIN_ERROR, errorMessage);
  3145. return;
  3146. }
  3147. if(!loopingForErrors) {
  3148. if(shared.getConfig()['cf.credentials.mode'] == 1) {
  3149. timeWaiting = 0;
  3150. document.querySelector('.login-wrapper input[name="email"]').value = shared.getConfig()['cf.credentials.email'];
  3151. document.querySelector('.login-wrapper input[name="password"]').value = shared.getConfig()['cf.credentials.password'];
  3152. document.querySelector('.login-wrapper button.login').click();
  3153. loopingForErrors = true;
  3154. } else {
  3155. if(document.querySelector('.login-wrapper input[name="email"]').value != '' && document.querySelector('.login-wrapper input[name="password"]').value != '') {
  3156. document.querySelector('.login-wrapper button.login').click();
  3157. document.getElementById('process-status').innerHTML = 'Processing';
  3158. loopingForErrors = true;
  3159. } else {
  3160. document.getElementById('process-status').innerHTML = 'Waiting for credentials...';
  3161. if (timeWaiting/1000 > (shared.getConfig()['defaults.timeout'] / 1.5) * 60) {
  3162. shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided');
  3163. return;
  3164. }
  3165. }
  3166. }
  3167. }
  3168. }
  3169. if (timeWaiting/1000 > shared.getConfig()['defaults.timeout'] * 60) {
  3170. shared.closeWithError(K.ErrorType.TIMEOUT, '');
  3171. return;
  3172. }
  3173. timeWaiting += 3000;
  3174. setTimeout(findLoginForm, helpers.randomMs(2000, 5000));
  3175. };
  3176. function interact() {
  3177. let selectables = [].concat([...document.querySelectorAll('td')], [...document.querySelectorAll('p')], [...document.querySelectorAll('th')]);
  3178. interactions.start(selectables);
  3179. setTimeout(waitInteractions, helpers.randomMs(2000, 4000));
  3180. }
  3181. function waitInteractions() {
  3182. if(interactions.completed()) {
  3183. roll();
  3184. } else {
  3185. setTimeout(waitInteractions, helpers.randomMs(2000, 4000));
  3186. }
  3187. }
  3188. function isCountdownVisible() {
  3189. countdown = document.querySelectorAll('.timeout-wrapper');
  3190. return (countdown.length > 0 && countdown[0].isVisible());
  3191. };
  3192. function isRollButtonVisible() {
  3193. rollButton = document.querySelectorAll('.main-button-2.roll-button.bg-2');
  3194. return (rollButton.length > 0 && rollButton[0].isVisible());
  3195. };
  3196. function roll() {
  3197. document.getElementById('process-status').innerHTML = 'Roll triggered';
  3198. rollButton[0].click();
  3199. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 3000));
  3200. }
  3201. function isPromotionTagVisible() {
  3202. let pTag = document.querySelector('p');
  3203. if (pTag) {
  3204. promotionTag = pTag;
  3205. return true;
  3206. }
  3207. return false;
  3208. };
  3209. function findPromotionTag() {
  3210. if( isPromotionTagVisible() ) {
  3211. processRunDetails();
  3212. } else {
  3213. setTimeout(findPromotionTag, helpers.randomMs(2000, 5000));
  3214. }
  3215. };
  3216. function processRunDetails() {
  3217. let result = {};
  3218. if(navigationProcess == NavigationProcess.ROLLING) {
  3219. result.claimed = readClaimed();
  3220. result.balance = readBalance();
  3221. if(result.claimed != 0) {
  3222. result.rolledNumber = readRolledNumber();
  3223. }
  3224. // To adjust nextRoll if it failed to load before reading it:
  3225. let minOneHour = result.rolledNumber && result.rolledNumber != 0;
  3226. result.nextRoll = readCountdown(minOneHour);
  3227. result.balance = readBalance();
  3228. } else if (navigationProcess == NavigationProcess.PROCESSING_PROMOTION) {
  3229. result.promoStatus = readPromoStatus();
  3230. result.promoCode = readPromoCode();
  3231. if (result.promoStatus == K.CF.PromoStatus.ACCEPTED) {
  3232. result.nextRoll = (new Date(59000)).getTime();
  3233. }
  3234. }
  3235. shared.closeWindow(result);
  3236. };
  3237. function readCountdown(minOneHour = false) {
  3238. let minsElement = document.querySelector('.timeout-container .minutes .digits');
  3239. let mins = "0";
  3240. if (minsElement) {
  3241. mins = minsElement.innerHTML;
  3242. }
  3243. if (mins) {
  3244. let estimated = helpers.addMinutes(+mins + 1);
  3245. let oneHour = Date.now() + (60*60*1000);
  3246. if (minOneHour && (oneHour > estimated) ) {
  3247. return oneHour;
  3248. }
  3249. return estimated;
  3250. } else {
  3251. return null;
  3252. }
  3253. };
  3254. function readClaimed() {
  3255. let claimed = 0;
  3256. try {
  3257. claimed = document.querySelector('.result').innerHTML;
  3258. claimed = claimed.trim();
  3259. claimed = claimed.slice(claimed.lastIndexOf(" ") + 1);
  3260. } catch(err) { }
  3261. return claimed;
  3262. };
  3263. function readRolledNumber() {
  3264. let number = 0;
  3265. try {
  3266. number = [...document.querySelectorAll('.lucky-number')].map(x => x.innerText).join('');
  3267. number = parseInt(number);
  3268. } catch(err) { }
  3269. return number;
  3270. };
  3271. function readBalance() {
  3272. let balance = "";
  3273. try {
  3274. balance = document.querySelector('.navbar-coins.bg-1 a').innerText;
  3275. } catch(err) { }
  3276. return balance;
  3277. };
  3278. function readPromoStatus() {
  3279. let promoStatus = K.CF.PromoStatus.UNKNOWNERROR;
  3280. try {
  3281. if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeAccepted) > 0) {
  3282. return K.CF.PromoStatus.ACCEPTED;
  3283. } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeUsed) > 0) {
  3284. return K.CF.PromoStatus.USEDBEFORE;
  3285. } else if(promotionTag.innerHTML.indexOf(localeConfig.stringSearches.promoCodeExpired) > 0) {
  3286. return K.CF.PromoStatus.EXPIRED;
  3287. } else if(localeConfig.stringSearches.promoCodeInvalid.findIndex(x => promotionTag.innerHTML.indexOf(x) > -1) == -1) {
  3288. return K.CF.PromoStatus.INVALID;
  3289. }
  3290. } catch ( err ) { }
  3291. return promoStatus;
  3292. };
  3293. function validatePromoString() {
  3294. };
  3295. function readPromoCode() {
  3296. var urlSplit = window.location.href.split('/');
  3297. return urlSplit[urlSplit.length - 1];
  3298. };
  3299. function displayStatusUi() {
  3300. let wrapper = document.createElement('div');
  3301. wrapper.innerHTML = '<div class="withdraw-button bg-2" style="top:30%; z-index:1500;" href="#">⚙️ <span id="process-status">Processing</span></div>';
  3302. document.querySelector( 'body' ).prepend( wrapper.firstChild );
  3303. };
  3304. return {
  3305. init: init
  3306. };
  3307. },
  3308. createCFHistory: function() {
  3309. let rollsMeta = [
  3310. { id: 0, range: '0000-9885', count: 0 },
  3311. { id: 1, range: '9886-9985', count: 0 },
  3312. { id: 2, range: '9986-9993', count: 0 },
  3313. { id: 3, range: '9994-9997', count: 0 },
  3314. { id: 4, range: '9998-9999', count: 0 },
  3315. { id: 5, range: '10000', count: 0 }
  3316. ];
  3317. function initOrLoad() {
  3318. let storedData = persistence.load('CFHistory', true);
  3319. if(storedData) {
  3320. rollsMeta = storedData;
  3321. }
  3322. };
  3323. function addRoll(number) {
  3324. switch(true) {
  3325. case (number <= 9885):
  3326. rollsMeta[0].count++;
  3327. break;
  3328. case (number <= 9985):
  3329. rollsMeta[1].count++;
  3330. break;
  3331. case (number <= 9993):
  3332. rollsMeta[2].count++;
  3333. break;
  3334. case (number <= 9997):
  3335. rollsMeta[3].count++;
  3336. break;
  3337. case (number <= 9999):
  3338. rollsMeta[4].count++;
  3339. break;
  3340. case (number == 10000):
  3341. rollsMeta[5].count++;
  3342. break;
  3343. default:
  3344. break;
  3345. }
  3346. save();
  3347. };
  3348. function getRollsMeta() {
  3349. return rollsMeta.map(x => x.count);
  3350. };
  3351. function save() {
  3352. persistence.save('CFHistory', rollsMeta, true);
  3353. };
  3354. return {
  3355. initOrLoad: initOrLoad,
  3356. addRoll: addRoll,
  3357. getRollsMeta: getRollsMeta
  3358. }
  3359. },
  3360. createFBProcessor: function() {
  3361. let countdownMinutes;
  3362. let timeout = new Timeout(this.maxSeconds);
  3363. let captcha = new HCaptchaWidget();
  3364. function run() {
  3365. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  3366. };
  3367. function findCountdownOrRollButton() {
  3368. if ( isCountdownVisible() ) {
  3369. timeout.restart();
  3370. countdownMinutes = +document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount')[0].innerHTML + 1;
  3371. let result = {};
  3372. result.balance = readBalance();
  3373. result.nextRoll = helpers.addMinutes(countdownMinutes.toString());
  3374. shared.closeWindow(result);
  3375. return;
  3376. }
  3377. if ( isRollButtonVisible() ) {
  3378. // if (shared.getConfig()['fb.activateRPBonus']) {
  3379. // if (!document.getElementById('bonus_container_free_points')) {
  3380. // document.querySelector('a.rewards_link').click();
  3381. // activateBonus(0);
  3382. // }
  3383. // }
  3384. try {
  3385. let doBonus = false; // true;
  3386. if (doBonus) {
  3387. if (!document.getElementById('bonus_span_free_wof')) {
  3388. RedeemRPProduct('free_wof_5');
  3389. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  3390. return;
  3391. }
  3392. }
  3393. } catch { }
  3394. /* For 'Play without captcha accounts' */
  3395. if (!captcha.isUserFriendly) {
  3396. clickRoll()
  3397. } else {
  3398. captcha.isSolved().then(() => { clickRoll(); });
  3399. }
  3400. } else {
  3401. setTimeout(findCountdownOrRollButton, helpers.randomMs(2000, 5000));
  3402. }
  3403. };
  3404. function isCountdownVisible() {
  3405. return document.querySelectorAll('.free_play_time_remaining.hasCountdown .countdown_amount').length > 0;
  3406. };
  3407. function isHCaptchaVisible() {
  3408. let hCaptchaFrame = document.querySelector('.h-captcha > iframe');
  3409. if (hCaptchaFrame && hCaptchaFrame.isVisible()) {
  3410. return true;
  3411. }
  3412. return false;
  3413. };
  3414. function isRollButtonVisible() {
  3415. return document.getElementById('free_play_form_button').isVisible();
  3416. };
  3417. function clickRoll() {
  3418. try {
  3419. document.getElementById('free_play_form_button').click();
  3420. setTimeout(processRunDetails, helpers.randomMs(3000, 10000));
  3421. } catch (err) {
  3422. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  3423. }
  3424. };
  3425. function processRunDetails() {
  3426. if (document.getElementById('winnings').isVisible()) {
  3427. closePopup();
  3428. let result = {};
  3429. result.claimed = readClaimed();
  3430. result.balance = readBalance();
  3431. if(result.claimed != 0) {
  3432. result.rolledNumber = readRolledNumber();
  3433. }
  3434. shared.closeWindow(result);
  3435. return;
  3436. }
  3437. if (document.querySelector('.free_play_result_error').isVisible()) {
  3438. shared.closeWithError(K.ErrorType.ROLL_ERROR, document.querySelector('.free_play_result_error').innerHTML);
  3439. return;
  3440. }
  3441. if(document.getElementById('free_play_error').isVisible()) {
  3442. shared.closeWithError(K.ErrorType.ROLL_ERROR, document.querySelector('.free_play_error').innerHTML);
  3443. return;
  3444. }
  3445. if (document.getElementById('same_ip_error').isVisible()) {
  3446. shared.closeWithError(K.ErrorType.ROLL_ERROR, document.getElementById('same_ip_error').innerHTML);
  3447. return;
  3448. }
  3449. setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
  3450. };
  3451. function closePopup() {
  3452. let closePopupBtn = document.querySelector('.reveal-modal.open .close-reveal-modal');
  3453. if (closePopupBtn) {
  3454. closePopupBtn.click();
  3455. }
  3456. };
  3457. function readRolledNumber() {
  3458. let rolled = 0;
  3459. try {
  3460. rolled = parseInt([... document.querySelectorAll('#free_play_digits span')].map( x => x.innerHTML).join(''));
  3461. } catch { }
  3462. return rolled;
  3463. };
  3464. function readBalance() {
  3465. let balance = 0;
  3466. try {
  3467. balance = document.getElementById('balance').innerHTML;
  3468. } catch { }
  3469. return balance;
  3470. };
  3471. function readClaimed() {
  3472. let claimed = 0;
  3473. try {
  3474. claimed = document.getElementById('winnings').innerHTML;
  3475. } catch { }
  3476. return claimed;
  3477. };
  3478. // function activateBonus(i) {
  3479. // if(document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_error')) {
  3480. // let closeBtn = document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_box_close')
  3481. // if (closeBtn.isVisible()) {
  3482. // closeBtn.click();
  3483. // }
  3484. // } else if (document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_success')) {
  3485. // let closeBtn = document.querySelector('#reward_point_redeem_result_container_div .reward_point_redeem_result_box_close')
  3486. // if (closeBtn.isVisible()) {
  3487. // closeBtn.click();
  3488. // document.querySelector('#free_play_link_li a').click();
  3489. // setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
  3490. // return;
  3491. // }
  3492. // }
  3493. // try {
  3494. // let redeemButtons = document.querySelectorAll('#free_points_rewards button');
  3495. // redeemButtons[i].click();
  3496. // i = i + 1;
  3497. // } catch (err) {
  3498. // }
  3499. // if(i > 4) {
  3500. // document.querySelector('#free_play_link_li a').click();
  3501. // setTimeout(findCountdownOrRollButton, helpers.randomMs(10000, 12000));
  3502. // return;
  3503. // }
  3504. // setTimeout(activateBonus.bind(null, i), 5000);
  3505. // };
  3506. return {
  3507. run: run
  3508. };
  3509. },
  3510. createFPProcessor: function() {
  3511. let timeout = new Timeout(this.maxSeconds);
  3512. let captcha = new HCaptchaWidget();
  3513. function init() {
  3514. if(window.location.href.includes('ptc/view')) {
  3515. addDuration();
  3516. ptcSingle();
  3517. } else if (window.location.href.includes('ptc')) {
  3518. ptcList();
  3519. } else if (window.location.href.includes('account/login')) {
  3520. tryLogin();
  3521. } else if (window.location.href.includes('page/user-admin')) {
  3522. window.location.href = 'https://faucetpay.io/ptc';
  3523. }
  3524. return;
  3525. }
  3526. function tryLogin() {
  3527. let username = document.querySelector('input[name="user_name"');
  3528. let password = document.querySelector('input[name="password"');
  3529. let captcha = document.querySelector('.h-captcha > iframe');
  3530. let btn = document.querySelector('button[type="submit"');
  3531. if (username && password && btn && username.value != '' && password.value != '') {
  3532. //WAIT FOR CAPTCHA => THEN CLICK BTN
  3533. if ( captcha && captcha.getAttribute('data-hcaptcha-response').length > 0 ) {
  3534. btn.click();
  3535. } else {
  3536. setTimeout(tryLogin, helpers.randomMs(9000, 11000));
  3537. }
  3538. } else {
  3539. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  3540. }
  3541. }
  3542. function addDuration() {
  3543. let duration = document.querySelector('#duration');
  3544. if(duration && !isNaN(duration.innerText)) {
  3545. timeout.restart(parseInt(duration.innerText));
  3546. } else {
  3547. setTimeout(addDuration, 10000);
  3548. }
  3549. }
  3550. function ptcList() {
  3551. let result;
  3552. let runMsgDiv = document.querySelector('.alert.alert-info');
  3553. if (runMsgDiv) {
  3554. let runMsg = runMsgDiv.innerHTML;
  3555. if (runMsg.includes('invalid captcha')) {
  3556. // Warn? Usually an error if ptcList is refreshed
  3557. } else if (runMsg.includes('Good job')) {
  3558. // "Good job! You have been credited with 0.00000001 BTC."
  3559. try {
  3560. let idx = runMsg.search(/\d/);
  3561. let claimed = parseFloat(runMsg.slice(idx, idx + 10));
  3562. result = shared.getResult();
  3563. result.claimed = (result.claimed ?? 0) + claimed;
  3564. // result.nextRoll = helpers.addMs(helpers.getRandomMs(shared.getConfig()['fp.hoursBetweenRuns'] * 60, 2)); // Wait hoursBetweenRuns +/- 1% //TODO: SLEEP CHECK
  3565. shared.updateWithoutClosing(result);
  3566. } catch { }
  3567. }
  3568. }
  3569. if ([...document.querySelectorAll('b')].filter(x => x.innerText.includes('Whoops!')).length > 0) {
  3570. result = shared.getResult();
  3571. shared.closeWindow(result);
  3572. return;
  3573. }
  3574. let adButtons = [...document.querySelectorAll('button')].filter(x => x .innerHTML.includes('VISIT AD FOR'));
  3575. if (adButtons.length > 0) {
  3576. adButtons[helpers.randomInt(0, adButtons.length-1)].click();
  3577. return;
  3578. }
  3579. setTimeout(ptcList, helpers.randomMs(10000, 12000));
  3580. }
  3581. function ptcSingle() {
  3582. if(document.querySelector('input[name="complete"]').isVisible()) {
  3583. captcha.isSolved().then(() => { clickClaim(); });
  3584. } else if (document.querySelector('body').innerText.toLowerCase().includes('ad does not exist')) {
  3585. window.location.href = 'https://faucetpay.io/ptc';
  3586. } else {
  3587. setTimeout(ptcSingle, helpers.randomMs(5000, 6000));
  3588. }
  3589. }
  3590. function clickClaim() {
  3591. let input = document.querySelector('input[name="complete"]');
  3592. input.focus();
  3593. input.onclick = '';
  3594. input.click();
  3595. //force close with timeout in case it's still opened
  3596. setTimeout(shared.closeWithError.bind(null, 'TIMEOUT', 'Timed out after clicking a CLAIM button.'), helpers.minToMs(shared.getConfig()['defaults.timeout']));
  3597. }
  3598. return {
  3599. init: init
  3600. };
  3601. },
  3602. createBagiKeranProcessor: function() {
  3603. let timeout = new Timeout(this.maxSeconds);
  3604. let hcaptcha = new HCaptchaWidget({selector: '.h-captcha > iframe, .hcaptcha > iframe, .g-recaptcha > iframe'});
  3605. let captcha = new BKCaptchaWidget({selector: ''});
  3606. let elements = {
  3607. errorDivs: function() {
  3608. return document.querySelectorAll('.alert.alert-danger');
  3609. },
  3610. warningDivs: function() {
  3611. return document.querySelectorAll('.alert.alert-warning');
  3612. },
  3613. successDivs: function() {
  3614. return document.querySelectorAll('.alert.alert-success');
  3615. },
  3616. blockCloudflare: function() {
  3617. return document.querySelector('h1[data-translate="block_headline"]');
  3618. },
  3619. errorCloudflare: function() {
  3620. if (document.title != 'Please Wait... | Cloudflare' && !document.querySelector('#cf-hcaptcha-container')) {
  3621. return document.querySelector('#cf-error-details p');
  3622. } else {
  3623. return null;
  3624. }
  3625. },
  3626. openLoginModalButton: function() {
  3627. return document.getElementById('submit');
  3628. },
  3629. modal: function() {
  3630. return document.querySelector('#myModal.show');
  3631. },
  3632. addressInput: function() {
  3633. return document.querySelector('input[name="address"]');
  3634. },
  3635. submitButton: function() {
  3636. return document.querySelector('#myModal button[type="submit"]');
  3637. },
  3638. openClaimModalButton: function() {
  3639. return document.querySelector('form button[type="submit"]');
  3640. },
  3641. openWithdrawModal: function() {
  3642. return document.getElementById('submit');
  3643. },
  3644. linkWithdrawMinNotReached: function() {
  3645. return document.querySelector('a.btn.btn-primary.btn-block');
  3646. }
  3647. };
  3648. function init() {
  3649. 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:
  3650. //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
  3651. shared.devlog(`${window.location.href} signing out`);
  3652. shared.getCurrent().params.doSignOut = false;
  3653. shared.saveFlowControl();
  3654. window.location.href = (new URL('signout.php', window.location.href)).href;;
  3655. return;
  3656. }
  3657. if (window.location.href.includes('captha.php')) {
  3658. setTimeout(runCaptchaPage, helpers.randomMs(1000, 2000));
  3659. return;
  3660. } else if (window.location.href.includes('withdraw.php')) {
  3661. setTimeout(runWithdraw, helpers.randomMs(1000, 2000));
  3662. return;
  3663. } else {
  3664. setTimeout(run, helpers.randomMs(1000, 2000));
  3665. return;
  3666. }
  3667. }
  3668. function run() {
  3669. readAlerts();
  3670. processIndex();
  3671. };
  3672. function runCaptchaPage() {
  3673. readAlerts();
  3674. shared.clearRetries();
  3675. processCaptchaPage();
  3676. }
  3677. function runWithdraw() {
  3678. readAlerts();
  3679. shared.clearRetries();
  3680. processWithdraw();
  3681. }
  3682. function readAlerts() {
  3683. let elm;
  3684. elements.warningDivs().forEach(function (elem) {
  3685. 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>"
  3686. let result = {};
  3687. try {
  3688. let mins = elem.innerText.split('\n')[1].replace(/\D/g, '');
  3689. result.nextRoll = helpers.addMinutes(mins);
  3690. } catch { } // result.nextRoll = helpers.addMinutes(60);
  3691. if (shared.getCurrent().params.doWithdraw) {
  3692. shared.updateWithoutClosing(result);
  3693. window.location.href = (new URL('withdraw.php', window.location.href)).href;
  3694. } else {
  3695. shared.closeWindow(result);
  3696. }
  3697. return;
  3698. }
  3699. });
  3700. elements.successDivs().forEach(function (elem) {
  3701. if (elem) {
  3702. if (elem.innerText.includes('claimed successfully')) { // "You've claimed successfully 2 Satoshi BTC." ...
  3703. let result = {};
  3704. // result.nextRoll = helpers.addMinutes(60);
  3705. result.claimed = 0;
  3706. try {
  3707. let val = elem.innerText.split('\n')[0].replace(/\D/g, '');
  3708. if (typeof val == 'string') {
  3709. val = +val;
  3710. }
  3711. if (Number.isInteger(val)) {
  3712. val = val / 100000000;
  3713. }
  3714. result.claimed = val;
  3715. } catch { }
  3716. try {
  3717. let mins = elem.innerText.split('\n')[1].replace(/\D/g, '');
  3718. result.nextRoll = helpers.addMinutes(mins);
  3719. } catch { }
  3720. if (shared.getCurrent().params.doWithdraw) {
  3721. shared.updateWithoutClosing(result);
  3722. let link = elem.querySelector('a');
  3723. if (link && link.innerText.includes('withdraw')) {
  3724. link.click();
  3725. return;
  3726. } else {
  3727. window.location.href = (new URL('withdraw.php', window.location.href)).href;;
  3728. }
  3729. }
  3730. shared.closeWindow(result);
  3731. return;
  3732. } 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>
  3733. let result = {};
  3734. result.withdrawnAmount = 0;
  3735. let val = elem.innerHTML.split(' ')[0];
  3736. if (typeof val == 'string') {
  3737. val = +val;
  3738. }
  3739. if (Number.isInteger(val)) {
  3740. val = val / 100000000;
  3741. }
  3742. result.withdrawnAmount = val;
  3743. shared.closeWindow(result);
  3744. return;
  3745. }
  3746. }
  3747. });
  3748. elm = elements.blockCloudflare();
  3749. if (elm) {
  3750. shared.closeWithError(K.ErrorType.IP_BAN, document.title + ' | ' + elm.innerText); // "Sorry, you have been blocked"
  3751. return;
  3752. }
  3753. elm = elements.errorCloudflare();
  3754. if (elm) {
  3755. shared.closeWithError(K.ErrorType.IP_RESTRICTED, document.title + ' | ' + elm.innerText); // "Access denied | bagi.co.in used Cloudflare to restrict access" @document.title
  3756. return;
  3757. }
  3758. elements.errorDivs().forEach(function (elem) {
  3759. if (elem) {
  3760. if (elem.innerText.toLowerCase().includes('vpn/proxy/tor')) { // "VPN/Proxy/Tor is not allowed on this faucet." ...
  3761. shared.closeWithError(K.ErrorType.IP_ERROR, elem.innerText);
  3762. return;
  3763. } else if (elem.innerText.toLowerCase().includes('look valid')) { // The Bitcoin Address doesn't look valid
  3764. //invalid address
  3765. shared.closeWithError(K.ErrorType.ADDRESS_ERROR, elem.innerText);
  3766. return;
  3767. } else if (elem.innerText.toLowerCase().includes('login not valid')) { // Login Not Valid, Please reLogin
  3768. // TODO: FIX => ITS NOT WORKING BECAUSE B/K REALOADS ITSELF TOO MANY TIMES
  3769. // FORCE 1 RETRY as sometimes it might work
  3770. if(shared.isRetrying()) {
  3771. shared.devlog(`${window.location.href} login retry failed`);
  3772. shared.closeWithError(K.ErrorType.LOGIN_ERROR, elem.innerText);
  3773. } else {
  3774. shared.devlog(`${window.location.href} will retry to login`);
  3775. // @KayDee workaraound
  3776. var curLoc = window.location.href;
  3777. if (curLoc.includes('index')) {
  3778. window.location.replace(curLoc.replace('index','withdraw'));
  3779. }
  3780. else {
  3781. window.location.replace(curLoc+'index.php');
  3782. }
  3783. }
  3784. return;
  3785. } else if (elem.innerText.toLowerCase().includes('claim not valid')) { // Claim not Valid, Please reClaim. Try again
  3786. // FORCE 1 RETRY
  3787. if(shared.isRetrying()) {
  3788. shared.devlog(`${window.location.href} claim retry failed`);
  3789. shared.closeWithError(K.ErrorType.CLAIM_ERROR, elem.innerText);
  3790. } else {
  3791. shared.devlog(`${window.location.href} will retry to claim`);
  3792. // @KayDee workaraound
  3793. window.location.replace(window.location.href);
  3794. }
  3795. return;
  3796. } else if (elem.innerText.toLowerCase().includes('captcha is wrong')) {
  3797. // FORCE 1 RETRY
  3798. if(shared.isRetrying()) {
  3799. shared.devlog(`${window.location.href} claim retry failed`);
  3800. shared.closeWithError(K.ErrorType.CLAIM_ERROR, elem.innerText);
  3801. } else {
  3802. shared.devlog(`${window.location.href} will retry to claim`);
  3803. // @KayDee workaraound
  3804. window.location.replace(window.location.href);
  3805. }
  3806. return;
  3807. } else {
  3808. // Unknown issue
  3809. shared.closeWithError(K.ErrorType.ERROR, elem.innerText);
  3810. return;
  3811. }
  3812. }
  3813. });
  3814. elm = elements.linkWithdrawMinNotReached();
  3815. if (elm) {
  3816. if(elm.innerText.toLowerCase().includes('minimum withdraw')) { // Minimum Withdraw is ...
  3817. shared.closeWithError(K.ErrorType.MIN_WITHDRAW_ERROR, elm.innerText);
  3818. return;
  3819. }
  3820. }
  3821. }
  3822. function processIndex() {
  3823. if (elements.modal() && elements.addressInput() && elements.submitButton()) { // 2. Fill address & click Login
  3824. if(elements.addressInput().value != '') {
  3825. captcha.isSolved().then(() => {
  3826. let kcInput = document.querySelector('input[name="kodecaptcha"]');
  3827. if(elements.submitButton() && kcInput && kcInput.value != '' ) {
  3828. if(hcaptcha.isUserFriendly) {
  3829. shared.devlog('hCaptcha detected');
  3830. hcaptcha.isSolved().then(() => {
  3831. shared.devlog('Clicking LOGIN after hCaptcha');
  3832. elements.submitButton().click(); // should redirect
  3833. return;
  3834. });
  3835. } else {
  3836. shared.devlog('hCaptcha not detected');
  3837. shared.devlog('Clicking LOGIN');
  3838. elements.submitButton().click(); // should redirect
  3839. return;
  3840. }
  3841. }
  3842. });
  3843. return;
  3844. // elements.submitButton().click(); // shoud redirect but check for timeout
  3845. } else {
  3846. elements.addressInput().value = shared.getCurrent().params.address;
  3847. }
  3848. setTimeout(run, helpers.randomMs(2000, 4000));
  3849. return;
  3850. }
  3851. if (elements.openLoginModalButton()) { // 1. Click the Get Started Button
  3852. elements.openLoginModalButton().click();
  3853. timeout.restart();
  3854. setTimeout(processIndex, helpers.randomMs(1000, 3000));
  3855. return;
  3856. }
  3857. if (elements.openClaimModalButton()) { // Claim Bitcoin Button
  3858. elements.openClaimModalButton().click();
  3859. timeout.restart();
  3860. setTimeout(processIndex, helpers.randomMs(2000, 4000));
  3861. return;
  3862. }
  3863. setTimeout(run, helpers.randomMs(2000, 4000));
  3864. };
  3865. function processCaptchaPage() {
  3866. shared.devlog(`@processCaptchaPage`);
  3867. if(elements.modal()) {
  3868. captcha.isSolved().then(() => {
  3869. let kcInput = document.querySelector('input[name="kodecaptcha"]');
  3870. if(elements.submitButton() && kcInput && kcInput.value != '' ) {
  3871. if(hcaptcha.isUserFriendly) {
  3872. shared.devlog('hCaptcha detected');
  3873. hcaptcha.isSolved().then(() => {
  3874. shared.devlog('Clicking SUBMIT after hCaptcha');
  3875. elements.submitButton().click(); // should redirect
  3876. return;
  3877. });
  3878. } else {
  3879. shared.devlog('hCaptcha not detected');
  3880. shared.devlog('Clicking SUBMIT');
  3881. elements.submitButton().click(); // should redirect
  3882. return;
  3883. }
  3884. }
  3885. });
  3886. return;
  3887. }
  3888. if (elements.openLoginModalButton()) { // 1. Click the Claim Button to open the modal w/the hCaptcha
  3889. elements.openLoginModalButton().click();
  3890. timeout.restart();
  3891. setTimeout(processCaptchaPage, helpers.randomMs(1000, 3000));
  3892. return;
  3893. }
  3894. setTimeout(runCaptchaPage, helpers.randomMs(2000, 4000));
  3895. }
  3896. function processWithdraw() {
  3897. if(elements.modal()) {
  3898. captcha.isSolved().then(() => {
  3899. let kcInput = document.querySelector('input[name="kodecaptcha"]');
  3900. if(elements.submitButton() && kcInput && kcInput.value != '' ) {
  3901. if(hcaptcha.isUserFriendly) {
  3902. shared.devlog('hCaptcha detected');
  3903. hcaptcha.isSolved().then(() => {
  3904. shared.devlog('Clicking SUBMIT after hCaptcha');
  3905. elements.submitButton().click(); // should redirect
  3906. return;
  3907. });
  3908. } else {
  3909. shared.devlog('hCaptcha not detected');
  3910. shared.devlog('Clicking SUBMIT');
  3911. elements.submitButton().click(); // should redirect
  3912. return;
  3913. }
  3914. }
  3915. });
  3916. return;
  3917. }
  3918. if (elements.openWithdrawModal()) { // 1. Click the Withdraw to FaucetPay submit button to open the modal w/the hCaptcha
  3919. elements.openWithdrawModal().click();
  3920. timeout.restart();
  3921. setTimeout(processWithdraw, helpers.randomMs(2000, 4000));
  3922. return;
  3923. }
  3924. setTimeout(runWithdraw, helpers.randomMs(2000, 4000));
  3925. }
  3926. return {
  3927. init: init
  3928. };
  3929. },
  3930. createOkFaucetProcessor: function() {
  3931. let timeout = new Timeout(this.maxSeconds);
  3932. let countdownMinutes;
  3933. let captcha = new HCaptchaWidget();
  3934. let selectElement = {
  3935. addressInput: function() {
  3936. return document.querySelector('input[type="text"]');
  3937. },
  3938. rollButton: function() {
  3939. return document.querySelector('input[type="submit"');
  3940. },
  3941. countdown: function() { // "You have to wait\n60 minutes"
  3942. let successDivs = document.querySelectorAll(".alert.alert-success");
  3943. if(successDivs.length == 1 && successDivs[0].isVisible()) {
  3944. return parseInt(successDivs[0].innerText.replace(/\D/g, ''));
  3945. }
  3946. return null;
  3947. },
  3948. rolledNumber: function() {
  3949. let successDivs = document.querySelectorAll(".alert.alert-success");
  3950. if(successDivs && successDivs.length > 1 && successDivs[0].isVisible()) {
  3951. return parseInt(successDivs[0].innerText);
  3952. } else {
  3953. return null;
  3954. }
  3955. },
  3956. claimedAmount: function() {
  3957. let successDivs = document.querySelectorAll(".alert.alert-success");
  3958. if(successDivs && successDivs.length > 1 && successDivs[0].isVisible()) {
  3959. let val = parseInt(successDivs[1].innerText.replace(/\D/g, ''));
  3960. if (Number.isInteger(val)) {
  3961. val = val / 100000000;
  3962. }
  3963. return val;
  3964. } else {
  3965. return null;
  3966. }
  3967. },
  3968. error: function () {
  3969. let errorDiv = document.querySelector(".alert.alert-danger");
  3970. if(errorDiv) {
  3971. if (errorDiv.innerText.toLowerCase().includes('not have sufficient funds')) {
  3972. shared.closeWithError(K.ErrorType.NO_FUNDS, errorDiv.innerText);
  3973. } else {
  3974. shared.closeWithError(K.ErrorType.ERROR, errorDiv.innerText);
  3975. }
  3976. } else {
  3977. return null;
  3978. }
  3979. }
  3980. };
  3981. function init() {
  3982. run();
  3983. }
  3984. function run() {
  3985. try {
  3986. setTimeout(findResultCountdownOrRollButton, helpers.randomMs(12000, 15000));
  3987. } catch (err) {
  3988. shared.closeWithErrors(K.ErrorType.ERROR, err);
  3989. }
  3990. };
  3991. function findResultCountdownOrRollButton() {
  3992. selectElement.error();
  3993. if ( selectElement.countdown() ) {
  3994. shared.devlog(`Ok: countdown found`);
  3995. timeout.restart();
  3996. let result = {};
  3997. result.nextRoll = helpers.addMinutes(selectElement.countdown().toString());
  3998. shared.closeWindow(result);
  3999. return;
  4000. }
  4001. if ( isRollButtonVisible() ) {
  4002. startRoll();
  4003. return;
  4004. }
  4005. if (selectElement.claimedAmount()) {
  4006. processRunDetails();
  4007. return;
  4008. }
  4009. setTimeout(findResultCountdownOrRollButton, helpers.randomMs(10000, 12000));
  4010. };
  4011. function startRoll() {
  4012. shared.devlog(`Ok: rollbutton found`);
  4013. let addressInput = selectElement.addressInput();
  4014. if (addressInput && addressInput.value != shared.getCurrent().params.address) {
  4015. addressInput.value = shared.getCurrent().params.address;
  4016. shared.devlog(`Ok: address filled`);
  4017. }
  4018. captcha.isSolved().then(() => { clickRoll(); });
  4019. };
  4020. function isHCaptchaVisible() {
  4021. let hCaptchaFrame = document.querySelector('.h-captcha > iframe');
  4022. if (hCaptchaFrame && hCaptchaFrame.isVisible()) {
  4023. return true;
  4024. }
  4025. return false;
  4026. };
  4027. function isRollButtonVisible() {
  4028. let rollButton = selectElement.rollButton();
  4029. return rollButton && rollButton.isVisible();
  4030. };
  4031. function clickRoll() {
  4032. try {
  4033. shared.devlog(`Clicking roll button`);
  4034. selectElement.rollButton().click();
  4035. return;
  4036. } catch (err) {
  4037. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  4038. }
  4039. };
  4040. function processRunDetails() {
  4041. shared.devlog(`Ok: claimedAmount found`);
  4042. let claimedAmount = selectElement.claimedAmount();
  4043. let rolledNumber = selectElement.rolledNumber();
  4044. if (claimedAmount && rolledNumber) {
  4045. let result = {};
  4046. result.claimed = claimedAmount;
  4047. result.rolledNumber = rolledNumber;
  4048. shared.closeWindow(result);
  4049. return;
  4050. }
  4051. setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
  4052. };
  4053. return {
  4054. init: init
  4055. };
  4056. },
  4057. createBigBtcProcessor: function() {
  4058. let timeout = new Timeout(this.maxSeconds);
  4059. let countdownMinutes;
  4060. let captcha = new HCaptchaWidget();
  4061. let selectElement = {
  4062. loadingDiv: function() {
  4063. let loading = document.querySelector('#loading');
  4064. if (loading && loading.isVisible()) {
  4065. return true;
  4066. } else {
  4067. return false;
  4068. }
  4069. },
  4070. addressInput: function() {
  4071. return document.querySelector('#login input[name="address"]');
  4072. },
  4073. loginButton: function() {
  4074. return document.querySelector('#login input[type="submit"]');
  4075. },
  4076. claimButton: function() {
  4077. return document.getElementById('claimbutn');
  4078. },
  4079. countdown: function() { // "You have to wait\n60 minutes"
  4080. let cd = document.getElementById('countdown');
  4081. if(cd && cd.isVisible()) {
  4082. return parseInt(cd.innerText);
  4083. }
  4084. return null;
  4085. },
  4086. claimedAmount: function() {
  4087. let elm = document.querySelector('.alert.alert-success.pulse'); //"Yuppie! You won 2 satoshi!"
  4088. if(elm && elm.isVisible()) {
  4089. let val = parseInt(elm.innerText.replace(/\D/g, ''));
  4090. if (Number.isInteger(val)) {
  4091. val = val / 100000000;
  4092. }
  4093. return val;
  4094. } else {
  4095. return null;
  4096. }
  4097. },
  4098. balance: function() {
  4099. let elm = document.querySelector('a b');
  4100. if (elm && elm.isVisible()) {
  4101. let val = parseInt(elm.innerText.replace(',', ''));
  4102. if (Number.isInteger(val)) {
  4103. val = val / 100000000;
  4104. }
  4105. return val;
  4106. } else {
  4107. return null;
  4108. }
  4109. },
  4110. error: function () {
  4111. return null;
  4112. }
  4113. };
  4114. function init() {
  4115. if (window.location.href.includes('/faucet')) {
  4116. setTimeout(runFaucet, helpers.randomMs(12000, 14000));
  4117. return;
  4118. } else {
  4119. setTimeout(run, helpers.randomMs(3000, 5000));
  4120. return;
  4121. }
  4122. }
  4123. function run() {
  4124. try {
  4125. setTimeout(waitIfLoading, helpers.randomMs(12000, 15000));
  4126. } catch (err) {
  4127. shared.closeWithErrors(K.ErrorType.ERROR, err);
  4128. }
  4129. };
  4130. function doLogin() {
  4131. let address = selectElement.addressInput();
  4132. if(address && address.value != shared.getCurrent().params.address) {
  4133. address.value = shared.getCurrent().params.address;
  4134. } else {
  4135. selectElement.loginButton().click();
  4136. return;
  4137. }
  4138. setTimeout( doLogin , helpers.randomMs(1000, 2000));
  4139. };
  4140. function waitIfLoading() {
  4141. if ( !selectElement.loadingDiv() ) {
  4142. shared.devlog(`BigBtc: doing log in`);
  4143. doLogin();
  4144. return;
  4145. } else {
  4146. shared.devlog(`BigBtc: waiting for login form`);
  4147. }
  4148. setTimeout(waitIfLoading, helpers.randomMs(5000, 7000));
  4149. };
  4150. function runFaucet() {
  4151. let claimedAmount = selectElement.claimedAmount();
  4152. if(claimedAmount) {
  4153. shared.devlog(`@runFaucet: has claimed amount: ${claimedAmount}`);
  4154. processRunDetails();
  4155. return;
  4156. } else if (selectElement.countdown()) {
  4157. // need to wait
  4158. shared.devlog(`@runFaucet: has countdown: ${selectElement.countdown()}`);
  4159. let result = {};
  4160. shared.closeWindow(result);
  4161. } else {
  4162. shared.devlog(`BigBtc: waiting for captcha`);
  4163. captcha.isSolved().then(() => { clickClaim(); });
  4164. }
  4165. }
  4166. function clickClaim() {
  4167. try {
  4168. shared.devlog('Clicking roll button');
  4169. selectElement.claimButton().click();
  4170. return;
  4171. } catch (err) {
  4172. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  4173. }
  4174. };
  4175. function processRunDetails() {
  4176. shared.devlog(`BigBtc: processing results`);
  4177. let claimedAmount = selectElement.claimedAmount();
  4178. let balance = selectElement.balance();
  4179. let countdown = selectElement.countdown();
  4180. if (claimedAmount && balance) {
  4181. let result = {};
  4182. result.claimed = claimedAmount;
  4183. result.balance = balance;
  4184. // result.nextRoll = getDelayedNext();
  4185. shared.closeWindow(result);
  4186. return;
  4187. }
  4188. setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
  4189. };
  4190. return {
  4191. init: init
  4192. };
  4193. },
  4194. createBestChangeProcessor: function() {
  4195. let timeout = new Timeout(this.maxSeconds);
  4196. let countdownMinutes;
  4197. let captcha = new HCaptchaWidget({selector: '.hcaptcha > iframe'});
  4198. let elements = {
  4199. captcha: function() {
  4200. return document.querySelector('.hcaptcha > iframe');
  4201. },
  4202. container: function() {
  4203. return document.querySelector('#info_bonus');
  4204. },
  4205. containerOpener: function() {
  4206. return document.querySelector('#tab_bonus a');
  4207. },
  4208. addressInput: function() {
  4209. return document.querySelector('#bonus_purse');
  4210. },
  4211. claimButton: function() {
  4212. return document.querySelector('#bonus_button');
  4213. },
  4214. countdown: function() { // Time left: mm:ss
  4215. let elm = document.querySelector('#bonus_button');
  4216. try {
  4217. if (elm.value) {
  4218. let timeLeft = elm.value.split(':');
  4219. if (timeLeft.length > 1) {
  4220. return parseInt(timeLeft[1]);
  4221. }
  4222. }
  4223. } catch (err) {
  4224. return null;
  4225. }
  4226. },
  4227. claimedAmount: function() {
  4228. let elm = document.querySelector("#bonus_status b");
  4229. try {
  4230. let sats = elm.innerText.replace(/\D/g, '');
  4231. return sats / 100000000;
  4232. } catch (err) {
  4233. return null;
  4234. }
  4235. },
  4236. balance: function() {
  4237. let elm = document.querySelector("#faucet_unpaid_balance b");
  4238. try {
  4239. let sats = elm.innerText.replace(/\D/g, '');
  4240. return sats / 100000000;
  4241. } catch (err) {
  4242. return null;
  4243. }
  4244. }
  4245. };
  4246. function init() {
  4247. run();
  4248. }
  4249. function run() {
  4250. try {
  4251. if (!elements.container().isUserFriendly()) {
  4252. let co = elements.containerOpener();
  4253. if(co.isUserFriendly()) {
  4254. co.onclick = co.onmousedown;
  4255. co.click();
  4256. }
  4257. }
  4258. setTimeout(findCountdownOrRoll, helpers.randomMs(4000, 5000));
  4259. } catch (err) {
  4260. shared.closeWithErrors(K.ErrorType.ERROR, err);
  4261. }
  4262. };
  4263. function findCountdownOrRoll() {
  4264. let countdown = elements.countdown();
  4265. if(countdown) {
  4266. let result = { };
  4267. result.nextRoll = helpers.addMinutes(countdown.toString());
  4268. shared.closeWindow(result);
  4269. return;
  4270. }
  4271. let ai = elements.addressInput();
  4272. if (ai.isUserFriendly()) {
  4273. if (ai.value != shared.getCurrent().params.address) {
  4274. ai.value = shared.getCurrent().params.address;
  4275. }
  4276. captcha.isSolved().then(() => { clickClaim(); });
  4277. return;
  4278. }
  4279. setTimeout(findCountdownOrRoll, helpers.randomMs(10000, 12000));
  4280. };
  4281. function clickClaim() {
  4282. try {
  4283. shared.devlog('Clicking claim button');
  4284. let btn = elements.claimButton();
  4285. if(btn.isUserFriendly()) {
  4286. btn.click();
  4287. setTimeout(processRunDetails, helpers.randomMs(4000, 8000));
  4288. }
  4289. return;
  4290. } catch (err) {
  4291. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  4292. }
  4293. };
  4294. function processRunDetails() {
  4295. let claimedAmount = elements.claimedAmount();
  4296. let balance = elements.balance();
  4297. if (claimedAmount && balance) {
  4298. let result = {};
  4299. result.claimed = claimedAmount;
  4300. result.balance = balance;
  4301. // result.nextRoll = helpers.addMinutes(60);
  4302. shared.closeWindow(result);
  4303. return;
  4304. }
  4305. setTimeout(processRunDetails, helpers.randomMs(5000, 6000));
  4306. };
  4307. return {
  4308. init: init
  4309. };
  4310. },
  4311. };
  4312. function overrideSelectNativeJS_Functions () {
  4313. window.alert = function alert (message) {
  4314. console.log (message);
  4315. }
  4316. }
  4317. function addJS_Node (text, s_URL, funcToRun) {
  4318. var scriptNode= document.createElement ('script');
  4319. scriptNode.type= "text/javascript";
  4320. if (text)scriptNode.textContent= text;
  4321. if (s_URL)scriptNode.src= s_URL;
  4322. if (funcToRun)scriptNode.textContent = '(' + funcToRun.toString() + ')()';
  4323. var element = document.getElementsByTagName ('head')[0] || document.body || document.documentElement;
  4324. element.appendChild (scriptNode);
  4325. }
  4326. function detectWeb() {
  4327. // Temp until JTFey logo size is fixed
  4328. try {
  4329. if (window.location.href.includes('james-trussy')) {
  4330. document.querySelector('.navbar-brand img.img-fluid').style.maxWidth = "75px";
  4331. }
  4332. } catch(err) {}
  4333. if(!shared.isOpenedByManager()) {
  4334. shared.devlog(`${window.location.href} dismissed`);
  4335. return;
  4336. }
  4337. shared.devlog(`${window.location.href} accepted`);
  4338. let typeFromManager = shared.getCurrent().type;
  4339. timer = new Timer(false, 20, typeFromManager);
  4340. switch( typeFromManager ) {
  4341. case K.WebType.STORMGAIN:
  4342. SiteProcessor = objectGenerator.createSGProcessor();
  4343. setTimeout(SiteProcessor.run, helpers.randomMs(10000, 20000));
  4344. break;
  4345. case K.WebType.CRYPTOSFAUCETS:
  4346. SiteProcessor = objectGenerator.createCFProcessor();
  4347. setTimeout(SiteProcessor.init, helpers.randomMs(1000, 3000));
  4348. break;
  4349. case K.WebType.FREEBITCOIN:
  4350. SiteProcessor = objectGenerator.createFBProcessor();
  4351. setTimeout(SiteProcessor.run, helpers.randomMs(2000, 5000));
  4352. break;
  4353. case K.WebType.FREELITECOIN:
  4354. SiteProcessor = new FreeLitecoin();
  4355. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4356. break;
  4357. case K.WebType.FREEETHEREUMIO:
  4358. SiteProcessor = new FreeEthereumIo();
  4359. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4360. break;
  4361. case K.WebType.BAGIKERAN:
  4362. SiteProcessor = objectGenerator.createBagiKeranProcessor();
  4363. setTimeout(SiteProcessor.init, helpers.randomMs(5000, 10000));
  4364. break;
  4365. case K.WebType.FAUCETPAY:
  4366. SiteProcessor = objectGenerator.createFPProcessor();
  4367. setTimeout(SiteProcessor.init, helpers.randomMs(2000, 5000));
  4368. break;
  4369. case K.WebType.OKFAUCET:
  4370. SiteProcessor = objectGenerator.createOkFaucetProcessor();
  4371. setTimeout(SiteProcessor.init, helpers.randomMs(4000, 6000));
  4372. break;
  4373. case K.WebType.BIGBTC:
  4374. SiteProcessor = objectGenerator.createBigBtcProcessor();
  4375. setTimeout(SiteProcessor.init, helpers.randomMs(2000, 4000));
  4376. break;
  4377. case K.WebType.BESTCHANGE:
  4378. SiteProcessor = objectGenerator.createBestChangeProcessor();
  4379. setTimeout(SiteProcessor.init, helpers.randomMs(4000, 6000));
  4380. break;
  4381. case K.WebType.KINGBIZ:
  4382. SiteProcessor = new KingBiz();
  4383. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4384. break;
  4385. case K.WebType.FREEDOGEIO:
  4386. SiteProcessor = new FreeDogeIo();
  4387. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4388. break;
  4389. case K.WebType.BETFURYBOX:
  4390. SiteProcessor = new BetFuryBox(helpers.getEnumText(K.CMC, shared.getCurrent().params.cmc).toLowerCase());
  4391. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4392. break;
  4393. case K.WebType.DUTCHYROLL:
  4394. SiteProcessor = new DutchyRoll();
  4395. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4396. break;
  4397. case K.WebType.FCRYPTO:
  4398. SiteProcessor = new FCryptoRoll();
  4399. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(2000, 5000));
  4400. break;
  4401. case K.WebType.CBG:
  4402. SiteProcessor = new CBGRoll();
  4403. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4404. break;
  4405. case K.WebType.FPB:
  4406. SiteProcessor = new FPB(shared.getCurrent().params.sitePrefix);
  4407. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4408. break;
  4409. case K.WebType.G8:
  4410. SiteProcessor = new G8();
  4411. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4412. break;
  4413. case K.WebType.FREEGRC:
  4414. SiteProcessor = new GRCRoll();
  4415. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4416. break;
  4417. case K.WebType.HELI:
  4418. SiteProcessor = new Heli();
  4419. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4420. break;
  4421. case K.WebType.VIE:
  4422. SiteProcessor = new VieRoll();
  4423. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4424. break;
  4425. case K.WebType.O24:
  4426. SiteProcessor = new O24Roll();
  4427. setTimeout(() => { SiteProcessor.init() }, helpers.randomMs(3000, 5000));
  4428. break;
  4429. default:
  4430. break;
  4431. }
  4432. }
  4433. // CLASSES (WIP)
  4434. class ServerErrorRefresh {
  4435. constructor () {
  4436. this._refreshableTitles = [/500.*server error/, /524.*timeout/];
  4437. this._interval = setInterval( () => {
  4438. try {
  4439. let title = window.document.title;
  4440. if(title) {
  4441. if(this._refreshableTitles.some( (exp) => title.toLowerCase().match(exp) )) {
  4442. shared.devlog(`Refreshing site with title: ${title}`);
  4443. window.location.reload();
  4444. }
  4445. clearInterval(this._interval);
  4446. }
  4447. } catch {}
  4448. }, 15000);
  4449. }
  4450. }
  4451. class Timeout {
  4452. constructor(seconds) {
  4453. this.wait = seconds || shared.getConfig()['defaults.timeout'] * 60;
  4454. this.startedAt;
  4455. this.interval;
  4456. this.cb = (() => { shared.closeWithError(K.ErrorType.TIMEOUT, '') });
  4457. this.restart();
  4458. this._serverErrorRefresh = new ServerErrorRefresh();
  4459. }
  4460. get elapsed() {
  4461. return Date.now() - this.startedAt;
  4462. }
  4463. restart(addSeconds = false) {
  4464. if(this.interval) {
  4465. clearTimeout(this.interval);
  4466. }
  4467. this.startedAt = Date.now();
  4468. if(addSeconds) {
  4469. this.wait = this.wait + addSeconds;
  4470. }
  4471. this.interval = setTimeout( () => { this.cb() }, this.wait * 1000);
  4472. }
  4473. }
  4474. class Timer {
  4475. constructor(isManager, delaySeconds, webType) {
  4476. if(!useTimer || (webType && !Timer.webTypes().includes(webType))) {
  4477. return;
  4478. }
  4479. this.delay = delaySeconds * 1000;
  4480. if(!isManager) {
  4481. this.tick();
  4482. this.interval = setInterval(
  4483. () => { this.tick() }, this.delay);
  4484. }
  4485. }
  4486. static webTypes() { return [K.WebType.FREELITECOIN, K.WebType.FREEETHEREUMIO, K.WebType.BAGIKERAN, K.WebType.BIGBTC, K.WebType.FCRYPTO, K.WebType.FPB] };
  4487. startCheck(webType) {
  4488. if(!useTimer || (webType && !Timer.webTypes().includes(webType))) {
  4489. return;
  4490. }
  4491. persistence.save('lastAccess', Date.now());
  4492. this.interval = setInterval(
  4493. () => { this.isAlive() }, this.delay);
  4494. }
  4495. stopCheck() {
  4496. if(!useTimer) {
  4497. return;
  4498. }
  4499. clearInterval(timer.interval);
  4500. }
  4501. tick() {
  4502. if(!useTimer) {
  4503. return;
  4504. }
  4505. persistence.save('lastAccess', Date.now());
  4506. }
  4507. isAlive() {
  4508. if(!useTimer) {
  4509. return;
  4510. }
  4511. let now = Date.now();
  4512. let newAccess = persistence.load('lastAccess');
  4513. if(newAccess && (now - newAccess > this.delay)) {
  4514. //Close working tab and force restart
  4515. shared.devlog(`Timer is closing the working tab`);
  4516. shared.addError(K.ErrorType.FORCE_CLOSED, 'Site was unresponsive or redirected');
  4517. manager.closeWorkingTab();
  4518. }
  4519. }
  4520. }
  4521. const wait = ms => new Promise(resolve => setTimeout(resolve, ms || 3000));
  4522. class Parsers {
  4523. static innerText(elm) { // '0.12341234' => '0.12341234'
  4524. try {
  4525. return elm.innerText;
  4526. } catch (err) { }
  4527. }
  4528. static trimNaNs(elm) { // 'You won 0.12341234 TRX' => '0.12341234'
  4529. try {
  4530. return elm.innerText.replace(/[^\d.-]/g, '');
  4531. } catch (err) { }
  4532. }
  4533. static splitAndIdxTrimNaNs(elm, options) { // '17.96 Coins (17.50 + 0.46)' => 17.96
  4534. try {
  4535. return elm.innerText.split(options.splitter)[options.idx].replace(/[^\d.-]/g, '');
  4536. } catch (err) { }
  4537. }
  4538. static innerTextIntToFloat(elm) { // 'You won 1234 satoshis' => 0.00001234
  4539. try {
  4540. let sats = elm.innerText.replace(/\D/g, '');
  4541. return sats / 100000000;
  4542. } catch (err) { }
  4543. }
  4544. static innerTextJoinedToInt(elm) { // '7|2|9|6' => 7296
  4545. try {
  4546. return parseInt([... elm].map( x => x.innerText).join(''));
  4547. } catch (err) { }
  4548. }
  4549. static stormGainCountdown(elm) { // '3:01:01' => 120000
  4550. try {
  4551. let timeLeft = elm.innerText.split(':');
  4552. if (timeLeft[0] == 'Synchronizing') {
  4553. //TODO: should retry to load the value
  4554. }
  4555. if(timeLeft.length === 3) {
  4556. return parseInt(timeLeft[0]) * 60 + parseInt(timeLeft[1]);
  4557. }
  4558. } catch (err) {
  4559. return null;
  4560. }
  4561. }
  4562. static kingBizCountdown(elm) { // '4|2' => 42
  4563. try {
  4564. let itms = elm.querySelectorAll('.flip-clock-active .up');
  4565. if (itms.length > 1 && itms[0].isVisible() && itms[1].isVisible()) {
  4566. return parseInt([itms[0].innerText, itms[1].innerText].join(''));
  4567. }
  4568. } catch (err) {
  4569. return null;
  4570. }
  4571. }
  4572. static freeGrcCountdown(elm) { // 'Wait for 53:31 before next roll' => 53
  4573. try {
  4574. shared.devlog(`@Parsers.freeGrcCountdown: with element [${elm}]`);
  4575. let val = elm.innerText.split(':')[0];
  4576. val = val.replace(/[^\d.-]/g, '');
  4577. shared.devlog(`@Parsers.freeGrcCountdown returning`);
  4578. return parseInt(val);
  4579. } catch (err) {
  4580. shared.devlog(`@Parsers.freeGrcCountdown error: ${err}`);
  4581. return null;
  4582. }
  4583. }
  4584. static bestChangeCountdown(elm) { // '00:58:35' => 58
  4585. try {
  4586. if (elm.value) {
  4587. let timeLeft = elm.value.split(':');
  4588. if (timeLeft.length > 1) {
  4589. return parseInt(timeLeft[1]);
  4590. }
  4591. }
  4592. } catch (err) {
  4593. return null;
  4594. }
  4595. }
  4596. static freeEthereumIoClaimed(elm) { // 'You won 0.12341234 TRX and rolled number 7623' => 0.12341234
  4597. try {
  4598. let line = elm.innerHTML;
  4599. let idx = line.search(/0\./);
  4600. return parseFloat(line.slice(idx, idx + 10));
  4601. } catch (err) { }
  4602. }
  4603. static betFuryBoxClaimed(elm) {
  4604. try {
  4605. let currency = elm.querySelector('.free-box__withdraw-currency').innerText;
  4606. let val = elm.querySelector('.free-box__need-sum').innerText.replace(/ /g,'').split('/')[1];
  4607. // if (val.length < 10) {
  4608. if (currency == 'Satoshi') {
  4609. val = val/100000000;
  4610. }
  4611. return val;
  4612. } catch (err) {
  4613. return null;
  4614. }
  4615. }
  4616. static g8ClaimsLeft(elm) {
  4617. try {
  4618. if (elm.innerText.includes('\nYou have ')) { // 'Claim 183848 satoshi (0.00012 USD) every 20 Seconds\nYou have 70 claims left today.'
  4619. let val = elm.innerText.split('\nYou have ')[1].split(' ')[0];
  4620. // val = val/100000000;
  4621. return val;
  4622. } else {
  4623. shared.devlog(`@Parsers.g8ClaimsLeft not read: with element [${elm}]`);
  4624. return null;
  4625. }
  4626. } catch (err) {
  4627. shared.devlog(`@Parsers.g8ClaimsLeft not read: with element [${elm}] Error: ${err}`);
  4628. return null;
  4629. }
  4630. }
  4631. static cbgClaimed(elm) {
  4632. try {
  4633. if (elm.innerText.includes('was sent to')) { //?? was sent to you on...
  4634. let val = elm.innerText.trim().split(' ')[0];
  4635. if (elm.innerText.includes('oshi') || elm.innerText.includes('gwei')) {
  4636. val = val/100000000;
  4637. }
  4638. return val;
  4639. } else {
  4640. shared.devlog(`@Parsers.cbgClaimed not read: with element [${elm}]`);
  4641. return null;
  4642. }
  4643. } catch (err) {
  4644. shared.devlog(`@Parsers.cbgClaimed read error: with element [${elm}] Error: ${err}`);
  4645. return null;
  4646. }
  4647. }
  4648. static dutchysClaimed(elm) { // 'You Won :101 DUTCHY + 20 XP' => 101
  4649. try {
  4650. let splitted = elm.innerText.split('DUTCHY');
  4651. return splitted[0].replace(/[^\d.-]/g, '');
  4652. } catch (err) { shared.devlog(`@Parsers.dutchysClaimed, with element [${elm}] Error: ${err}`); }
  4653. }
  4654. static dutchysClaimedToFloat(elm) { // 'You Won :22437 ADA + 100 XP' => 0.00022437
  4655. try {
  4656. let sats = elm.innerText.split('+');
  4657. sats = sats[0].replace(/\D/g, '');
  4658. return sats / 100000000;
  4659. } catch (err) { shared.devlog(`@Parsers.dutchysClaimedToFloat, with element [${elm}] Error: ${err}`); }
  4660. }
  4661. static splitAndIdxToInt(elm, options) { // '26 Minutes 23' w/spliiter='Minutes' => 26
  4662. try {
  4663. return parseInt(elm.innerText.split(options.splitter)[options.idx].trim());
  4664. // return parseInt(elm.innerText.split('Minutes')[0].trim());
  4665. } catch (err) { shared.devlog(`Error @Parsers.splitAndIdxToInt: ${err}`); }
  4666. }
  4667. }
  4668. class CrawlerWidget {
  4669. constructor(params) {
  4670. if (!params || !params.selector) {
  4671. throw new Error('CrawlerWidget requires a selector parameter');
  4672. }
  4673. this.context = this.context || document;
  4674. Object.assign(this, params);
  4675. }
  4676. get isUserFriendly() {
  4677. // Changed to select the element each time
  4678. this.element = this.context.isUserFriendly(this.selector);
  4679. return this.element;
  4680. // this.element = this.element || this.context.isUserFriendly(this.selector);
  4681. // return this.element;
  4682. }
  4683. }
  4684. class ReadableWidget extends CrawlerWidget {
  4685. constructor(params) {
  4686. if (params && !params.parser) {
  4687. params.parser = Parsers.innerText; //default parser
  4688. }
  4689. super(params);
  4690. }
  4691. get value() {
  4692. if (this.isUserFriendly) {
  4693. return this.parser(this.element, this.options);
  4694. } else {
  4695. shared.devlog(`ReadableWidget (selector: '${this.selector}') cannot be read with the assigned parser`);
  4696. return '';
  4697. }
  4698. }
  4699. }
  4700. class TextboxWidget extends CrawlerWidget {
  4701. get value() {
  4702. if (!this.isUserFriendly) {
  4703. shared.devlog(`TextboxWidget (selector: '${this.selector}') cannot be access with the assigned parser`);
  4704. return '';
  4705. }
  4706. return this.element.value;
  4707. }
  4708. set value(newValue) {
  4709. if (!this.isUserFriendly) {
  4710. shared.devlog(`TextboxWidget (selector: '${this.selector}') cannot be access with the assigned parser`);
  4711. return '';
  4712. }
  4713. this.element.value = newValue;
  4714. return '';
  4715. }
  4716. }
  4717. class ButtonWidget extends CrawlerWidget {
  4718. // Overriding to select the button again, just in case fake buttons are used by the faucet
  4719. // get isUserFriendly() {
  4720. // this.element = this.context.isUserFriendly(this.selector);
  4721. // return this.element;
  4722. // }
  4723. click() {
  4724. if (this.isUserFriendly) {
  4725. this.element.click();
  4726. return Promise.resolve(true);
  4727. } else {
  4728. shared.devlog(`ButtonWidget (selector: '${this.selector}') cannot be clicked`);
  4729. }
  4730. }
  4731. }
  4732. class SubmitWidget extends CrawlerWidget {
  4733. click() {
  4734. shared.devlog(`SubmitWidget: click attempt`);
  4735. if (this.isUserFriendly) {
  4736. let frm = this.element;
  4737. while(frm.nodeName != 'FORM' && frm.nodeName != null) {
  4738. frm = frm.parentElement;
  4739. }
  4740. if (frm.nodeName == 'FORM') {
  4741. shared.devlog(`SubmitWidget submitting`);
  4742. frm.submit();
  4743. } else {
  4744. shared.devlog(`SubmitWidget form not found`);
  4745. return;
  4746. }
  4747. return Promise.resolve(true);
  4748. } else {
  4749. shared.devlog(`SubmitWidget (selector: '${this.selector}') cannot be trigger`);
  4750. }
  4751. }
  4752. }
  4753. class CountdownWidget extends CrawlerWidget {
  4754. constructor(params) {
  4755. if (params && !params.parser) {
  4756. params.parser = Parsers.innerText; //default parser
  4757. }
  4758. super(params);
  4759. }
  4760. get timeLeft() {
  4761. if (this.isUserFriendly) {
  4762. return this.parser(this.element, this.options);
  4763. } else {
  4764. throw new Error(`CountdownWidget (selector: '${this.selector}') cannot be read`);
  4765. }
  4766. }
  4767. }
  4768. class CaptchaWidget extends CrawlerWidget {
  4769. constructor(params) {
  4770. super(params);
  4771. }
  4772. solve() { return true; }
  4773. async isSolved() { return false; }
  4774. }
  4775. class HCaptchaWidget extends CaptchaWidget {
  4776. constructor(params) {
  4777. let defaultParams = {
  4778. selector: '.h-captcha > iframe',
  4779. waitMs: [1000, 5000],
  4780. timeoutMs: 4 * 60 * 1000
  4781. };
  4782. for (let p in params) {
  4783. defaultParams[p] = params[p];
  4784. }
  4785. super(defaultParams);
  4786. }
  4787. async isSolved() {
  4788. return wait().then( () => {
  4789. if (this.isUserFriendly && this.element.hasAttribute('data-hcaptcha-response') && this.element.getAttribute('data-hcaptcha-response').length > 0) {
  4790. return Promise.resolve(true);
  4791. }
  4792. return this.isSolved();
  4793. });
  4794. }
  4795. }
  4796. class ImageProcessor {
  4797. constructor(img) {
  4798. this._img = img;
  4799. }
  4800. isImageComplete() {
  4801. return this._img && this._img.complete;
  4802. }
  4803. createDrawer(width, height) {
  4804. let canvas = document.createElement('canvas');
  4805. canvas.setAttribute('width', width);
  4806. canvas.setAttribute('height', height);
  4807. let ctx = canvas.getContext('2d');
  4808. return {
  4809. canvas: canvas,
  4810. ctx: ctx
  4811. };
  4812. }
  4813. getDrawer() {
  4814. return this._drawer;
  4815. }
  4816. toCanvas() {
  4817. this._drawer = this.createDrawer(this._img.width, this._img.height);
  4818. this._drawer.ctx.drawImage(this._img, 0, 0);
  4819. }
  4820. foreach(filter) {
  4821. let imgData = this._drawer.ctx.getImageData(0, 0, this._drawer.canvas.width, this._drawer.canvas.height);
  4822. for (var x = 0; x < imgData.width; x++) {
  4823. for (var y = 0; y < imgData.height; y++) {
  4824. var i = x * 4 + y * 4 * imgData.width;
  4825. var pixel = { r: imgData.data[i + 0], g: imgData.data[i + 1], b: imgData.data[i + 2] };
  4826. pixel = filter(pixel);
  4827. imgData.data[i + 0] = pixel.r;
  4828. imgData.data[i + 1] = pixel.g;
  4829. imgData.data[i + 2] = pixel.b;
  4830. imgData.data[i + 3] = 255;
  4831. }
  4832. }
  4833. this._drawer.ctx.putImageData(imgData, 0, 0);
  4834. }
  4835. binarize (threshold) {
  4836. var image = this._drawer.canvas.getContext('2d').getImageData(0, 0, this._drawer.canvas.width, this._drawer.canvas.height);
  4837. for (var x = 0; x < image.width; x++) {
  4838. for (var y = 0; y < image.height; y++) {
  4839. var i = x * 4 + y * 4 * image.width;
  4840. var brightness = 0.34 * image.data[i] + 0.5 * image.data[i + 1] + 0.16 * image.data[i + 2];
  4841. image.data[i] = brightness >= threshold ? 255 : 0;
  4842. image.data[i + 1] = brightness >= threshold ? 255 : 0;
  4843. image.data[i + 2] = brightness >= threshold ? 255 : 0;
  4844. image.data[i + 3] = 255;
  4845. }
  4846. }
  4847. this._drawer.canvas.getContext('2d').putImageData(image, 0, 0);
  4848. }
  4849. invert(filter) {
  4850. this.foreach(function (p) {
  4851. p.r = 255 - p.r;
  4852. p.g = 255 - p.g;
  4853. p.b = 255 - p.b;
  4854. return p;
  4855. });
  4856. }
  4857. imgDataToBool(imgData) {
  4858. let character = [];
  4859. const data = imgData.data;
  4860. for (let i = 0; i < imgData.data.length; i += 4) {
  4861. let val = data[i] + data[i+1] + data[i+2];
  4862. character.push(val == 0 ? true : false);
  4863. }
  4864. return character;
  4865. }
  4866. }
  4867. class BKCaptchaWidget extends CaptchaWidget {
  4868. constructor() {
  4869. let defaultParams = {
  4870. selector: 'img[src="antibot.php"]',
  4871. waitMs: [1000, 5000],
  4872. timeoutMs: 4 * 60 * 1000
  4873. };
  4874. super(defaultParams);
  4875. this._imgProcessor;
  4876. this._characters = [];
  4877. }
  4878. charList() {
  4879. return [{"answer":"g","width":8,"height":9,"bools":[false,true,true,true,true,true,false,true,true,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]},
  4880. {"answer":"5","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4881. {"answer":"W","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true]},
  4882. {"answer":"O","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4883. {"answer":"N","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,true,false,false,false,true,true,true,true,true,true,false,false,true,true,true,true,true,true,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,true,true,true,true,true,true,false,false,false,true,true,true,true,true,false,false,false,true,true,true,true,true,false,false,false,false,true,true]},
  4884. {"answer":"T","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]},
  4885. {"answer":"q","width":8,"height":9,"bools":[false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true]},
  4886. {"answer":"l","width":4,"height":10,"bools":[true,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,true,true,true,true]},
  4887. {"answer":"B","width":8,"height":10,"bools":[true,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,false]},
  4888. {"answer":"3","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false,false]},
  4889. {"answer":"s","width":8,"height":7,"bools":[false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]},
  4890. {"answer":"p","width":8,"height":9,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]},
  4891. {"answer":"L","width":7,"height":10,"bools":[true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]},
  4892. {"answer":"Z","width":7,"height":10,"bools":[false,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]},
  4893. {"answer":"F","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]},
  4894. {"answer":"p","width":8,"height":9,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]},
  4895. {"answer":"T","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]},
  4896. {"answer":"8","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4897. {"answer":"P","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]},
  4898. {"answer":"J","width":6,"height":10,"bools":[false,false,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,true,false,false,false,true,true,true,true,false,true,true,false,false,true,true,true,false,false]},
  4899. {"answer":"y","width":8,"height":9,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,true,false,false,false,false,false,true,true,false,true,true,true,true,true,true,false]},
  4900. {"answer":"r","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4901. {"answer":"R","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,false,false,false,true,true,false,false,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4902. {"answer":"M","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4903. {"answer":"d","width":8,"height":10,"bools":[false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true]},
  4904. {"answer":"E","width":7,"height":10,"bools":[true,true,true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]},
  4905. {"answer":"7","width":8,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]},
  4906. {"answer":"Z","width":7,"height":10,"bools":[true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true]},
  4907. {"answer":"l","width":4,"height":10,"bools":[true,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,true,true,true,true]},
  4908. {"answer":"K","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,false,false,true,true,false,false,true,true,false,true,true,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true]},
  4909. {"answer":"6","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,false,false]},
  4910. {"answer":"H","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4911. {"answer":"5","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4912. {"answer":"Y","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]},
  4913. {"answer":"d","width":8,"height":10,"bools":[false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true]},
  4914. {"answer":"p","width":8,"height":9,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false]},
  4915. {"answer":"z","width":6,"height":7,"bools":[true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,true,true,false,false,false,true,true,false,false,false,true,true,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true]},
  4916. {"answer":"n","width":8,"height":7,"bools":[true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4917. {"answer":"a","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,true,false,true,true,true,true,false,true,true]},
  4918. {"answer":"8","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4919. {"answer":"t","width":8,"height":9,"bools":[false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false]},
  4920. {"answer":"q","width":8,"height":9,"bools":[false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true]},
  4921. {"answer":"a","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,true,false,true,true,true,true,false,true,true]},
  4922. {"answer":"Z","width":7,"height":10,"bools":[true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,true,true]},
  4923. {"answer":"1","width":6,"height":10,"bools":[false,false,true,true,false,false,false,true,true,true,false,false,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,true,true]},
  4924. {"answer":"m","width":8,"height":7,"bools":[true,false,true,true,false,true,true,false,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true]},
  4925. {"answer":"l","width":4,"height":10,"bools":[true,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,true,true,true,true]},
  4926. {"answer":"q","width":8,"height":9,"bools":[false,false,true,true,true,false,true,true,false,true,true,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true]},
  4927. {"answer":"C","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4928. {"answer":"a","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,true,false,true,true,true,true,false,true,true]},
  4929. {"answer":"2","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,true,true]},
  4930. {"answer":"h","width":8,"height":10,"bools":[true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4931. {"answer":"F","width":7,"height":10,"bools":[true,true,true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false]},
  4932. {"answer":"c","width":8,"height":7,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4933. {"answer":"P","width":8,"height":10,"bools":[true,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false]},
  4934. {"answer":"r","width":8,"height":7,"bools":[true,true,false,true,true,true,false,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false]},
  4935. {"answer":"Y","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false]},
  4936. {"answer":"S","width":8,"height":10,"bools":[false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]},
  4937. {"answer":"u","width":8,"height":7,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,true,false,false,true,true,true,false,true,true]},
  4938. {"answer":"M","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4939. {"answer":"S","width":8,"height":10,"bools":[false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]},
  4940. {"answer":"g","width":8,"height":9,"bools":[false,true,true,true,true,true,false,true,true,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,true,true,false,false,false,false,true,true,false,true,true,true,true,true,true,false]},
  4941. {"answer":"U","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4942. {"answer":"k","width":7,"height":10,"bools":[true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,true,true,false,true,true,false,true,true,false,false,true,true,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,false,false,true,true,false,false,true,true,false,true,true,false,false,false,true,true]},
  4943. {"answer":"4","width":8,"height":10,"bools":[false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,false,false,true,true,false,false,true,true,false,true,true,false,false,false,true,true,false,true,true,true,true,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false]},
  4944. {"answer":"A","width":8,"height":10,"bools":[false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4945. {"answer":"b","width":8,"height":10,"bools":[true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,true,true,false,false,true,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,true,false,false,true,true,false,true,true,false,true,true,true,false,false]},
  4946. {"answer":"I","width":6,"height":10,"bools":[true,true,true,true,true,true,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,true,true]},
  4947. {"answer":"o","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false]},
  4948. {"answer":"i","width":6,"height":10,"bools":[false,false,true,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,true,true,true,true,true,true]},
  4949. {"answer":"C","width":8,"height":10,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4950. {"answer":"e","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4951. {"answer":"w","width":8,"height":7,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,false,true,true,false,true,true,true,true,true,true,true,true,true,true,false,true,true,false,false,true,true,false]},
  4952. {"answer":"f","width":8,"height":10,"bools":[false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false]},
  4953. {"answer":"j","width":7,"height":12,"bools":[false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,false]},
  4954. {"answer":"F","width":6,"height":10,"bools":[true,true,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false,true,true,false,false,false,false]},
  4955. {"answer":"x","width":8,"height":7,"bools":[true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true]},
  4956. {"answer":"e","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4957. {"answer":"G","width":8,"height":10,"bools":[false,false,true,true,true,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,true,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4958. {"answer":"0","width":8,"height":10,"bools":[false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false]},
  4959. {"answer":"0","width":8,"height":10,"bools":[false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false]},
  4960. {"answer":"D","width":8,"height":10,"bools":[true,true,true,true,true,true,false,false,true,true,false,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,true,true,false,true,true,true,true,true,true,false,false]},
  4961. {"answer":"e","width":8,"height":7,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,true,true,true,true,true,true,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,true,true,true,false]},
  4962. {"answer":"X","width":8,"height":10,"bools":[true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true]},
  4963. {"answer":"Q","width":8,"height":10,"bools":[false,false,true,true,true,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,false,false,false,true,true,true,true,false,true,true,false,true,true,true,true,false,false,true,true,true,true,false,true,true,false,false,true,true,false,false,false,true,true,true,true,false,true]}];
  4964. }
  4965. async isReady() {
  4966. return wait().then( () => {
  4967. let img = document.querySelector(this.selector);
  4968. if(img && img.complete) {
  4969. shared.devlog(`@BKCaptcha isReady : true`);
  4970. this._imgProcessor = new ImageProcessor(img);
  4971. return Promise.resolve(true);
  4972. }
  4973. shared.devlog(`@BKCaptcha isReady : false`);
  4974. return this.isReady();
  4975. });
  4976. }
  4977. async isSolved() {
  4978. shared.devlog(`@BKCaptcha isSolved`);
  4979. return this.isReady()
  4980. .then( () => this.solve())
  4981. .then( (solution) => {
  4982. document.querySelector('input[name="kodecaptcha"]').value = solution;
  4983. return Promise.resolve(true);
  4984. })
  4985. .catch(err => {
  4986. shared.devlog(`@BKCaptcha error ${err}`);
  4987. return Promise.reject(`Error ${err}`);
  4988. });
  4989. }
  4990. preProcessImage() {
  4991. this._imgProcessor.toCanvas();
  4992. this._imgProcessor.binarize(200);
  4993. this._imgProcessor.invert();
  4994. shared.devlog(`@BKCaptcha preProcessImage: finished`);
  4995. }
  4996. cropCharacter(startFrom = 0) {
  4997. let imgData = this._imgProcessor.getDrawer().ctx.getImageData(startFrom, 0, this._imgProcessor.getDrawer().canvas.width - startFrom, this._imgProcessor.getDrawer().canvas.height);
  4998. let newBounds = { left: null, right:null, top: null, bottom: null };
  4999. let readingCharacter = false;
  5000. let endOfCharacter = null;
  5001. for (var x = 0; x < imgData.width; x++) {
  5002. if (endOfCharacter) {
  5003. newBounds.right = endOfCharacter;
  5004. break;
  5005. }
  5006. let isColumnEmpty = true;
  5007. for (var y = 0; y < imgData.height; y++) {
  5008. var i = x * 4 + y * 4 * imgData.width;
  5009. var pixel = { r: imgData.data[i + 0], g: imgData.data[i + 1], b: imgData.data[i + 2] };
  5010. if (pixel.r + pixel.g + pixel.b == 0) {
  5011. if (newBounds.left == null || newBounds.left > x) {
  5012. newBounds.left = x;
  5013. }
  5014. if (newBounds.right == null || newBounds.right < x) {
  5015. newBounds.right = x;
  5016. }
  5017. if (newBounds.top == null || newBounds.top > y) {
  5018. newBounds.top = y;
  5019. }
  5020. if (newBounds.bottom == null || newBounds.bottom < y) {
  5021. newBounds.bottom = y;
  5022. }
  5023. readingCharacter = true;
  5024. isColumnEmpty = false;
  5025. }
  5026. }
  5027. if (isColumnEmpty && readingCharacter) {
  5028. endOfCharacter = x - 1;
  5029. break;
  5030. }
  5031. }
  5032. return {
  5033. x: startFrom + newBounds.left,
  5034. y: newBounds.top,
  5035. width: newBounds.right - newBounds.left + 1,
  5036. height: newBounds.bottom - newBounds.top + 1,
  5037. nextBegins: startFrom + newBounds.right + 1
  5038. };
  5039. }
  5040. splitInCharacters() {
  5041. let chars = [];
  5042. let i =0;
  5043. do {
  5044. chars.push(this.cropCharacter( i== 0 ? 0 : chars[i-1].nextBegins ) );
  5045. let copy = document.createElement('canvas').getContext('2d');
  5046. copy.canvas.width = chars[i].width;
  5047. copy.canvas.height = chars[i].height;
  5048. let trimmedData = this._imgProcessor.getDrawer().ctx.getImageData(chars[i].x, chars[i].y, chars[i].width, chars[i].height);
  5049. copy.putImageData(trimmedData, 0, 0);
  5050. chars[i].bools = this._imgProcessor.imgDataToBool(trimmedData);
  5051. chars[i].dataUrl = copy.canvas.toDataURL("image/png");
  5052. i++;
  5053. } while(i < 5);
  5054. this._characters = chars;
  5055. }
  5056. guess(charElm) {
  5057. let bestGuess = {
  5058. answer: '',
  5059. blacksMatched: 0,
  5060. blacksMissed: 0,
  5061. percentageBlacks: 0,
  5062. exactMatch: false
  5063. };
  5064. let totalPixels = charElm.width * charElm.height;
  5065. let totalBlacks = charElm.bools.filter(x => x === true).length;
  5066. // console.log('Total Pixels:', totalPixels);
  5067. // console.log('Total Blacks:', totalBlacks);
  5068. // console.log(this.charList().length);
  5069. this.charList().filter(x => x.answer != '').forEach( function (elm) {
  5070. if (bestGuess.exactMatch) {
  5071. return;
  5072. }
  5073. if (charElm.width == elm.width && charElm.height == elm.height) {
  5074. // console.log(`${elm.answer} >> ${charElm.width} == ${elm.width} and ${charElm.height} == ${elm.height} > INSIDE`);
  5075. if (charElm.bools.join(',') == elm.bools.join(',')) {
  5076. // console.log(`EXACT MATCH!`);
  5077. bestGuess = {
  5078. answer: elm.answer,
  5079. percentageBlacks: 100,
  5080. exactMatch: true
  5081. };
  5082. return;
  5083. }
  5084. let blacksMatched = 0;
  5085. let blacksMissed = 0;
  5086. let percentageBlacks = 0;
  5087. for (let p = 0; p < totalPixels; p++) {
  5088. if (charElm.bools[p] === true || elm.bools[p] === true) {
  5089. if (elm.bools[p] == charElm.bools[p]) {
  5090. blacksMatched++;
  5091. } else {
  5092. blacksMissed++;
  5093. }
  5094. }
  5095. }
  5096. if (blacksMatched != 0 || blacksMissed != 0) {
  5097. percentageBlacks = blacksMatched/(blacksMatched + blacksMissed);
  5098. }
  5099. if (percentageBlacks > bestGuess.percentageBlacks) {
  5100. bestGuess = {
  5101. answer: elm.answer,
  5102. blacksMatched: blacksMatched,
  5103. blacksMissed: blacksMissed,
  5104. percentageBlacks: percentageBlacks
  5105. };
  5106. }
  5107. }
  5108. });
  5109. return bestGuess;
  5110. }
  5111. async solve() {
  5112. shared.devlog(`@BKCaptcha solve`);
  5113. let solution = '';
  5114. if(this._imgProcessor.isImageComplete()) {
  5115. this.preProcessImage();
  5116. this.splitInCharacters();
  5117. this._characters.forEach( ch => {
  5118. let bestGuess = this.guess(ch);
  5119. solution += bestGuess.answer;
  5120. shared.devlog(`@BKCaptcha Guessing: ${bestGuess.answer}`);
  5121. });
  5122. shared.devlog(`@BKCaptcha SOLUTION: ${solution}`);
  5123. }
  5124. // shared.devlog(`@BKCaptcha REJECTING (WAITING)`);
  5125. // return Promise.reject(`@BKCaptcha WAITING`);
  5126. // return (solution.length == this._segments.qty) ? Promise.resolve(solution) : Promise.reject(solution);
  5127. return Promise.resolve(solution);
  5128. }
  5129. }
  5130. class NoCaptchaWidget extends CaptchaWidget {
  5131. constructor(params) {
  5132. let defaultParams = {
  5133. selector: 'svg.feather-check-circle',
  5134. waitMs: 10000
  5135. };
  5136. for (let p in params) {
  5137. defaultParams[p] = params[p];
  5138. }
  5139. super(defaultParams);
  5140. }
  5141. async isSolved() {
  5142. return wait().then( () => {
  5143. if (this.isUserFriendly) {
  5144. shared.devlog(`@NoCaptcha solved`);
  5145. return Promise.resolve(true);
  5146. }
  5147. shared.devlog(`@NoCaptcha waiting`);
  5148. return this.isSolved();
  5149. });
  5150. }
  5151. }
  5152. class CBL01CaptchaWidget extends CaptchaWidget {
  5153. constructor(params) {
  5154. let defaultParams = {
  5155. selector: '',
  5156. waitMs: 2000
  5157. };
  5158. for (let p in params) {
  5159. defaultParams[p] = params[p];
  5160. }
  5161. super(defaultParams);
  5162. }
  5163. async isReady() {
  5164. return wait(1).then( () => {
  5165. if(this.isUserFriendly) {
  5166. shared.devlog(`@CBL01 isReady`);
  5167. return Promise.resolve(true);
  5168. }
  5169. return wait().then( () => { this.isReady(); });
  5170. });
  5171. }
  5172. async solve() {
  5173. let answer = document.getElementById('captchainput').value;
  5174. if (answer != '') {
  5175. // workaround for JJJ
  5176. if (answer.startsWith('JJJ')) {
  5177. answer = answer.slice(3);
  5178. document.getElementById('captchainput').value = answer;
  5179. }
  5180. if (answer.length != 6) {
  5181. shared.devlog(`@CBL1 too short or too long. Refreshing`);
  5182. document.getElementById('captchainput').value ='';
  5183. window.location.reload();
  5184. return wait(10000).then( () => { this.solve(); });
  5185. } else {
  5186. shared.devlog(`@CBL1 answer: ${answer}`);
  5187. return wait().then( () => { return true; } );
  5188. }
  5189. } else {
  5190. return wait().then( () => { this.solve(); });
  5191. }
  5192. }
  5193. async isSolved() {
  5194. return this.isReady()
  5195. .then( () => this.solve())
  5196. .then( (solution) => {
  5197. return Promise.resolve(true);
  5198. })
  5199. .catch(err => { shared.devlog(err); })
  5200. }
  5201. }
  5202. class D1CaptchaWidget extends CaptchaWidget {
  5203. constructor() {
  5204. let defaultParams = {
  5205. selector: '#submit_captcha span',
  5206. waitMs: [1000, 5000],
  5207. timeoutMs: 4 * 60 * 1000
  5208. };
  5209. super(defaultParams);
  5210. this.selectors = {
  5211. submitButton: '#submit',
  5212. answerSpan: '#submit_captcha span'
  5213. }
  5214. this._elements = {
  5215. submitButton: new ButtonWidget({selector: '#submit'}),
  5216. answerSpan: new ReadableWidget({selector: '#submit_captcha span'})
  5217. };
  5218. }
  5219. async isReady() {
  5220. return wait().then( () => {
  5221. if(this._elements.submitButton.isUserFriendly) {
  5222. shared.devlog(`@D1Captcha isReady`);
  5223. return Promise.resolve(true);
  5224. }
  5225. shared.devlog(`@D1Captcha waiting to be ready`);
  5226. return this.isReady();
  5227. });
  5228. }
  5229. async solve() {
  5230. if (this._elements.answerSpan.isUserFriendly) {
  5231. let answer = this._elements.answerSpan.value;
  5232. answer = answer ? answer.trim() : answer;
  5233. shared.devlog(`@D1Captcha answer: ${answer}`);
  5234. let input = document.querySelector(`input[value="${answer}"`);
  5235. if (input) {
  5236. shared.devlog(`@D1Captcha input for answer found!`);
  5237. helpers.alternativeClick(input.parentElement.querySelector('i'));
  5238. return wait().then( () => { return true; } );
  5239. } else {
  5240. shared.devlog(`@D1Captcha input for answer NOT FOUND!`);
  5241. return Promise.reject(`@D1Captcha input NOT FOUND for answer: ${answer}`);
  5242. }
  5243. } else {
  5244. shared.devlog(`@D1Captcha Answer span not found!!!`);
  5245. return Promise.reject('Answer span not found!!!');
  5246. }
  5247. }
  5248. async isSolved() {
  5249. return this.isReady()
  5250. .then( () => this.solve())
  5251. .then( (solution) => {
  5252. shared.devlog(`@D1Captcha => Solved`);
  5253. return Promise.resolve(true);
  5254. })
  5255. .catch(err => { shared.devlog(err); })
  5256. }
  5257. }
  5258. class Faucet {
  5259. constructor(elements, actions = {}) {
  5260. this._url = window.location.href;
  5261. this._timeout = new Timeout(this.maxSeconds);
  5262. this._elements = elements;
  5263. this._actions = {
  5264. preRun: false,
  5265. preRoll: false,
  5266. altValidation: false,
  5267. readClaimed: true,
  5268. readBalance: true,
  5269. readTimeLeft: true,
  5270. readRolledNumber: false,
  5271. isMultiClaim: false,
  5272. checkIfOutOfFunds: false,
  5273. preSaveResult: false
  5274. }
  5275. this._actions = { ...this._actions, ...actions };
  5276. this._params = shared.getCurrent().params || {};
  5277. this._result = this._actions.isMultiClaim ? (shared.getProp('tempResults') || {}) : (shared.getResult() || {});
  5278. }
  5279. checkCloudflareError() {
  5280. //TODO
  5281. }
  5282. useUrlListener() {
  5283. if (window.onurlchange === null) {
  5284. window.addEventListener('urlchange', (data) => {
  5285. if (this._url != window.location.href) {
  5286. shared.devlog(`Url changed from ${this._url} to ${window.location.href}`);
  5287. this._url = window.location.href;
  5288. this.resetRun();
  5289. }
  5290. });
  5291. }
  5292. }
  5293. resetRun() {
  5294. wait().then( () => { this.init(); });
  5295. }
  5296. init() {
  5297. throw new Error('Init not implemented!');
  5298. }
  5299. login() {
  5300. throw new Error('Login not implemented!'); //return NEED_TO_LOGIN
  5301. }
  5302. async run(action = false) {
  5303. if (this._actions.checkIfOutOfFunds) {
  5304. this.checkIfOutOfFunds();
  5305. }
  5306. if (this._actions.preRun) {
  5307. await wait().then( () => { this.preRun() } );;
  5308. }
  5309. if (!action) {
  5310. this.detectAction().then( (resolve) => {
  5311. shared.devlog(`@Run - Action detected: ${resolve.action}`);
  5312. this.perform(resolve.action);
  5313. });
  5314. } else {
  5315. this.perform(action);
  5316. }
  5317. }
  5318. perform(action) {
  5319. switch(action) {
  5320. case 'doRoll':
  5321. if(this._actions.preRoll) {
  5322. shared.devlog(`@Run - PREROLL`);
  5323. this.preRoll();
  5324. }
  5325. shared.devlog(`@Run - Captcha`);
  5326. this._elements.captcha.isSolved().then(() => { this.clickRoll() });
  5327. break;
  5328. case 'needToWait':
  5329. this.updateResult();
  5330. break;
  5331. default:
  5332. break;
  5333. }
  5334. }
  5335. async detectAction() {
  5336. // shared.devlog(`@detectAction`);
  5337. return wait().then( () => {
  5338. if ( this.isCountdownVisible() ) {
  5339. return Promise.resolve({action: 'needToWait'});
  5340. } else if ( this.isRollButtonVisible() ) {
  5341. return Promise.resolve({action: 'doRoll'});
  5342. } else {
  5343. return this.detectAction();
  5344. }
  5345. });
  5346. }
  5347. preRoll() {
  5348. throw new Error('PreRoll not implemented!');
  5349. }
  5350. preRun() {
  5351. throw new Error('PreRun not implemented!');
  5352. }
  5353. altValidation() {
  5354. throw new Error('AltValidation not implemented!');
  5355. }
  5356. isCountdownVisible() {
  5357. return this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly;
  5358. }
  5359. isRollButtonVisible() {
  5360. return this._elements.rollButton && this._elements.rollButton.isUserFriendly;
  5361. }
  5362. clickRoll() {
  5363. try {
  5364. shared.devlog('Clicking roll button');
  5365. this._elements.rollButton.click();
  5366. this.validateRun();
  5367. // setTimeout(() => { this.validateRun() }, helpers.randomMs(10000, 12000));
  5368. } catch (err) {
  5369. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  5370. }
  5371. }
  5372. failureValidation() {
  5373. throw new Error('FailureValidation not implemented!');
  5374. }
  5375. async validateRun() {
  5376. return wait(this._actions.useFailureValidation ? 6000 : null).then( () => {
  5377. if (this._actions.useFailureValidation) {
  5378. shared.devlog('@Doing FailureValidation');
  5379. if (this.failureValidation()) {
  5380. shared.devlog('@FailureValidation true => @Incorrect captcha');
  5381. return;
  5382. }
  5383. }
  5384. if (this._elements.success.isUserFriendly) {
  5385. shared.devlog('Successful run');
  5386. return this.updateResult();
  5387. } else if(this._actions.altValidation) {
  5388. if(this.altValidation()) {
  5389. shared.devlog('Alt validated');
  5390. return this.updateResult();
  5391. }
  5392. }
  5393. return wait(2000).then( () => { this.validateRun() });
  5394. });
  5395. }
  5396. async updateResult() {
  5397. // if (!this._actions.isMultiClaim) {
  5398. if(this._actions.readClaimed) {
  5399. this._result.claimed = this.readClaimed();
  5400. }
  5401. if(this._actions.readBalance) {
  5402. this._result.balance = this.readBalance();
  5403. }
  5404. if(this._actions.readTimeLeft) {
  5405. this._result.nextRoll = this.readNextRoll();
  5406. }
  5407. if(this._actions.readRolledNumber) {
  5408. this._result.rolledNumber = this.readRolledNumber();
  5409. }
  5410. shared.devlog(`Result: ${JSON.stringify(this._result)}`);
  5411. // }
  5412. if (this._actions.isMultiClaim) {
  5413. shared.devlog(`@updateResult as MultiClaim`);
  5414. shared.setProp('tempResults', this._result);
  5415. return this._actions.postRun ? this.postRun() : true;
  5416. }
  5417. if (this._actions.preSaveResult) {
  5418. this.preSaveResult();
  5419. }
  5420. if (this._actions.updateWithoutClosing) {
  5421. shared.updateWithoutClosing(this._result);
  5422. return this._actions.postRun ? this.postRun() : true;
  5423. } else {
  5424. shared.closeWindow(this._result);
  5425. }
  5426. }
  5427. readNextRoll() {
  5428. try {
  5429. if (this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly) {
  5430. shared.devlog(`@readNextRoll: ${helpers.addMinutes(this._elements.countdownMinutes.timeLeft)}`);
  5431. return helpers.addMinutes(this._elements.countdownMinutes.timeLeft);
  5432. }
  5433. } catch (err) { shared.devlog(`@readNextRoll: ${err}`); }
  5434. //return helpers.addMinutes(60);
  5435. return null;
  5436. }
  5437. readRolledNumber() {
  5438. let rolled = 0;
  5439. try {
  5440. if(this._elements.rolledNumber.isUserFriendly) {
  5441. rolled = this._elements.rolledNumber.value;
  5442. }
  5443. } catch (err) { shared.devlog(`@readRolledNumber: ${err}`); }
  5444. return rolled;
  5445. }
  5446. readBalance() {
  5447. let balance = 0;
  5448. try {
  5449. if(this._elements.balance.isUserFriendly) {
  5450. balance = this._elements.balance.value;
  5451. }
  5452. } catch (err) { shared.devlog(`@readBalance: ${err}`); }
  5453. return balance;
  5454. }
  5455. readClaimed() { //TODO: review if previous claimed should be received as arg
  5456. let claimed = this._result.claimed ?? 0;
  5457. if (this._actions.isMultiClaim) {
  5458. this._oldClaimed = claimed;
  5459. shared.devlog(`@readClaimed: oldClaimed set to ${this._oldClaimed}`);
  5460. } else {
  5461. shared.devlog(`@readClaimed: oldClaimed not set`);
  5462. }
  5463. try {
  5464. shared.devlog(`@readClaimed: isUserFriendly => ${this._elements.claimed.isUserFriendly}`);
  5465. if(this._elements.claimed.isUserFriendly) {
  5466. // shared.devlog(`@readClaimed: inside isUserFriendly`);
  5467. // shared.devlog(`InnerText: ${this._elements.claimed.isUserFriendly.innerText}`);
  5468. claimed = +claimed + +this._elements.claimed.value;
  5469. } else {
  5470. shared.devlog(`@readClaimed: NOT isUserFriendly`);
  5471. }
  5472. } catch (err) { shared.devlog(`@readClaimed: ${err}`); }
  5473. shared.devlog(`@readClaimed: returns ${claimed}`);
  5474. return claimed;
  5475. }
  5476. checkIfOutOfFunds() {
  5477. let divAlerts = [...document.querySelectorAll(this._elements.outOfFundsDivSelector)];
  5478. divAlerts.forEach( function (d) {
  5479. if (d.innerText.toLowerCase().includes('not have sufficient funds')) {
  5480. shared.closeWithError(K.ErrorType.FAUCET_EMPTY, d.innerText);
  5481. return;
  5482. }
  5483. });
  5484. }
  5485. }
  5486. class FreeEthereumIo extends Faucet {
  5487. constructor() {
  5488. let elements = {
  5489. countdownMinutes: new CountdownWidget({selector: '#cislo1'}),
  5490. rollButton: new ButtonWidget({selector: '#rollform button'}),
  5491. balance: new ReadableWidget({selector: '#cryptovalue'}),
  5492. claimed: new ReadableWidget({selector: '#info', parser: Parsers.freeEthereumIoClaimed}),
  5493. rolledNumber: new ReadableWidget({selector: '#numberroll'}),
  5494. captcha: new CBL01CaptchaWidget({selector: '#captchainput' }),
  5495. success: new ReadableWidget({selector: '#info'})
  5496. };
  5497. let actions = {
  5498. readRolledNumber: true,
  5499. useFailureValidation: true
  5500. };
  5501. super(elements, actions);
  5502. }
  5503. init() {
  5504. let url = new URL(this._url);
  5505. if (url.pathname == '/free/') {
  5506. if (document.querySelector('.h-captcha > iframe')) {
  5507. captcha = new HCaptchaWidget();
  5508. }
  5509. this.run();
  5510. } else if (url.pathname == '/') {
  5511. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5512. }
  5513. }
  5514. failureValidation() {
  5515. let elm = document.querySelector('#info');
  5516. if (elm && elm.innerText.toLowerCase().includes('incorrect')) {
  5517. shared.devlog(`@CBL1 invalid answer`);
  5518. document.getElementById('captchainput').value ='';
  5519. window.location.reload();
  5520. return true;
  5521. } else {
  5522. return false;
  5523. }
  5524. }
  5525. }
  5526. class FreeLitecoin extends Faucet {
  5527. constructor() {
  5528. let elements = {
  5529. countdownMinutes: new CountdownWidget({selector: '#cislo1'}),
  5530. rollButton: new ButtonWidget({selector: '#roll'}),
  5531. balance: new ReadableWidget({selector: '#money'}),
  5532. claimed: new ReadableWidget({selector: '#info', parser: Parsers.trimNaNs}),
  5533. rolledNumber: new ReadableWidget({selector: '#numberroll'}),
  5534. captcha: new CBL01CaptchaWidget({selector: '#captchainput' }),
  5535. success: new ReadableWidget({selector: '#info'})
  5536. };
  5537. let actions = {
  5538. readRolledNumber: true,
  5539. useFailureValidation: true
  5540. };
  5541. super(elements, actions);
  5542. }
  5543. init() {
  5544. let url = new URL(this._url);
  5545. if (url.pathname == '/') {
  5546. if (document.querySelector('.h-captcha > iframe')) {
  5547. captcha = new HCaptchaWidget();
  5548. }
  5549. this.run();
  5550. } else if (url.pathname.includes('/login')) {
  5551. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5552. }
  5553. }
  5554. failureValidation() {
  5555. let elm = document.querySelector('#numberroll');
  5556. if (elm && elm.innerText.toLowerCase().includes('incorrect')) {
  5557. shared.devlog(`@CBL1 invalid answer`);
  5558. document.getElementById('captchainput').value ='';
  5559. window.location.reload();
  5560. return true;
  5561. } else {
  5562. return false;
  5563. }
  5564. }
  5565. }
  5566. class FreeDogeIo extends Faucet {
  5567. constructor() {
  5568. let elements = {
  5569. countdownMinutes: new CountdownWidget({selector: '#cislo1'}),
  5570. rollButton: new ButtonWidget({selector: '.btn.btn-success'}),
  5571. balance: new ReadableWidget({selector: '#cryptovalue'}),
  5572. claimed: new ReadableWidget({selector: '#info', parser: Parsers.freeEthereumIoClaimed}),
  5573. rolledNumber: new ReadableWidget({selector: '#numberroll'}),
  5574. captcha: new CBL01CaptchaWidget({selector: '#captchainput' }),
  5575. success: new ReadableWidget({selector: '#info'})
  5576. };
  5577. let actions = {
  5578. readRolledNumber: true,
  5579. useFailureValidation: true
  5580. };
  5581. super(elements, actions);
  5582. }
  5583. init() {
  5584. let url = new URL(this._url);
  5585. if (url.pathname == '/free/') {
  5586. if (document.querySelector('.h-captcha > iframe')) {
  5587. captcha = new HCaptchaWidget();
  5588. }
  5589. this.run();
  5590. } else if (url.pathname == '/') {
  5591. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5592. }
  5593. }
  5594. failureValidation() {
  5595. let elm = document.querySelector('#info');
  5596. if (elm && elm.innerText.toLowerCase().includes('incorrect')) {
  5597. shared.devlog(`@CBL1 invalid answer`);
  5598. document.getElementById('captchainput').value = '';
  5599. window.location.reload();
  5600. return true;
  5601. } else {
  5602. return false;
  5603. }
  5604. }
  5605. }
  5606. class BetFuryBox extends Faucet {
  5607. constructor(coinPrefix, trySpin = false) {
  5608. let elements = {
  5609. preRunButton: new ButtonWidget({selector: '.free-box.free-box__' + coinPrefix + ' button'}), //'#' + coinPrefix + '_free_box_withdraw_page'}),
  5610. captcha: new HCaptchaWidget({selector: '.free-box-withdraw__captcha iframe'}),
  5611. //rollButton: new ButtonWidget({selector: '.modal__container button.button.button_md.button_red.fullwidth'}), //'#free_box_withdraw_popup'}),
  5612. rollButton: new ButtonWidget({selector: '.free-box-withdraw__footer .button_red.button_center.button_fullwidth'}),
  5613. success: new ReadableWidget({selector: '.modal:not(.free-box-withdraw,fury-wheel-modal), .vue-notification-template.my-notify.success'}),
  5614. claimed: new ReadableWidget({selector: '.free-box.free-box__' + coinPrefix, parser: Parsers.betFuryBoxClaimed}),
  5615. progressBar: new ReadableWidget({selector: '.free-box.free-box__' + coinPrefix + ' .free-box__progress-bar progress'}),
  5616. // loggedElm: new ReadableWidget({selector: '.btn-container .btn-wallet'}),
  5617. // notLoggedElm: new ReadableWidget({selector: '.btn-container.no-logged'}),
  5618. };
  5619. let actions = {
  5620. preRun: true,
  5621. readClaimed: true,
  5622. readBalance: false,
  5623. readRolledNumber: false
  5624. };
  5625. super(elements, actions);
  5626. this.coinPrefix = coinPrefix;
  5627. this.trySpin = trySpin;
  5628. }
  5629. init() {
  5630. if (this._url.includes('https://betfury.io/boxes/all')) {
  5631. this.run();
  5632. return;
  5633. } else {
  5634. return;
  5635. }
  5636. }
  5637. async spin() {
  5638. shared.devlog('Spinning...');
  5639. // TODO: wait for popup
  5640. // Click wheel
  5641. let clickables = document.querySelectorAll('.fury-wheel__wheel-btn, .fury-wheel__btn-wrap, .fury-wheel__btn-content, .fury-wheel__btn-img');
  5642. if (clickables.length > 0) {
  5643. clickables[Math.floor(Math.random()*clickables.length)].click();
  5644. // Wait for result and save it somewhere
  5645. // continue with the claim or just refresh the page to make it easier...
  5646. wait(15000).then ( () => { shared.closeWindow(this._result); } );
  5647. }
  5648. return;
  5649. }
  5650. async preRun() {
  5651. return wait().then( () => {
  5652. try {
  5653. // close opened popups
  5654. let popup = document.querySelector('.modal-wrapper .modal:not(.free-box-withdraw,fury-wheel-modal) .modal__btn-close');
  5655. // let popup = document.querySelector('.modal-wrapper .modal:not(.free-box-withdraw) .modal__btn-close');
  5656. if (popup) {
  5657. popup.click();
  5658. popup.click(); // twice
  5659. }
  5660. } catch (err) {}
  5661. if (this.trySpin) {
  5662. let spinUnavailable = document.querySelector('.bonus.bonus_furywheel.wait');
  5663. if (spinUnavailable) {
  5664. shared.devlog('Spin not available');
  5665. } else {
  5666. let spinBtn = document.querySelector('.wheel-amin'); //bonus bonus_furywheel wait
  5667. if (spinBtn) {
  5668. shared.devlog('Attempting spin');
  5669. spinBtn.click();
  5670. wait(10000).then ( () => { this.spin() } );
  5671. return wait(60000).then ( () => { this.preRun(); } );
  5672. }
  5673. }
  5674. }
  5675. // LOGIN CHECK REMOVED (throwing inconsistences)
  5676. // if (this._elements.notLoggedElm && this._elements.notLoggedElm.isUserFriendly &&
  5677. // this._elements.loggedElm && !this._elements.loggedElm.isUserFriendly) {
  5678. // shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5679. // return;
  5680. // }
  5681. // wait for progress bar...
  5682. if (!this._elements.progressBar || !this._elements.progressBar.isUserFriendly) {
  5683. return this.preRun();
  5684. }
  5685. if (this._elements.preRunButton.isUserFriendly) {
  5686. shared.devlog('@preRunButton is userfriendly');
  5687. if (!this._elements.preRunButton.isUserFriendly.disabled) {
  5688. shared.devlog('@preRunButton is userfriendly and enabled');
  5689. return this._elements.preRunButton.click();
  5690. } else {
  5691. this._timeout.restart();
  5692. shared.closeWindow(this._result);
  5693. return;
  5694. }
  5695. } else if (document.querySelectorAll('.free-box').length > 1) {
  5696. shared.devlog('list of boxes is userfriendly');
  5697. shared.closeWithError(K.ErrorType.ERROR, 'Box might not exist for your account.');
  5698. return;
  5699. }
  5700. return this.preRun();
  5701. });
  5702. }
  5703. // Custom Run Validation
  5704. async validateRun() {
  5705. shared.devlog('@validate BF');
  5706. return wait(7000).then( () => {
  5707. let popup = document.querySelector('.modal-wrapper .modal:not(.free-box-withdraw,fury-wheel-modal) .modal__btn-close');
  5708. if (!popup) {
  5709. shared.devlog('@validate post run popup not found');
  5710. if (this._elements.preRunButton.isUserFriendly && !this._elements.preRunButton.isUserFriendly.disabled) {
  5711. shared.devlog('@valide trying re-click');
  5712. this._elements.preRunButton.click();
  5713. return this.validateRun();
  5714. }
  5715. } else {
  5716. shared.devlog('@validate post run popup found');
  5717. try {
  5718. // let popup = document.querySelector('.modal-wrapper .modal:not(.free-box-withdraw) .modal__btn-close');
  5719. if (popup) {
  5720. popup.click();
  5721. popup.click();
  5722. }
  5723. } catch (err) {}
  5724. }
  5725. if (this._elements.success.isUserFriendly) {
  5726. shared.devlog('@validate BF Successful run');
  5727. return this.updateResult();
  5728. } else if(this._actions.altValidation) {
  5729. if(this.altValidation()) {
  5730. shared.devlog('Alt validated');
  5731. return this.updateResult();
  5732. }
  5733. }
  5734. return this.validateRun();
  5735. });
  5736. }
  5737. }
  5738. class KingBiz extends Faucet {
  5739. constructor() {
  5740. let elements = {
  5741. countdownMinutes: new CountdownWidget({selector: '#show_countdown_clock', parser: Parsers.kingBizCountdown}),
  5742. rollButton: new ButtonWidget({selector: 'input[value="ROLL"]:last-of-type'}),
  5743. balance: new ReadableWidget({selector: 'li.top_balance', parser: Parsers.trimNaNs}),
  5744. claimed: new ReadableWidget({selector: '#modal_header_msg', parser: Parsers.freeEthereumIoClaimed}),
  5745. rolledNumber: new ReadableWidget({selector: '#show_roll_numbers span', parser: Parsers.innerTextJoinedToInt}),
  5746. captcha: new HCaptchaWidget(),
  5747. success: new ReadableWidget({selector: '#show_roll_numbers span'})
  5748. };
  5749. let actions = {
  5750. readRolledNumber: true,
  5751. preRun: true
  5752. };
  5753. super(elements, actions);
  5754. }
  5755. init() {
  5756. if (this._url.includes('/faucet')) {
  5757. this.run();
  5758. return;
  5759. } else if (this._url.includes('/login')) {
  5760. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5761. return;
  5762. }
  5763. }
  5764. async preRun() {
  5765. let dangerDivs = document.querySelectorAll('.alert.alert-danger');
  5766. if (dangerDivs.length > 0) {
  5767. let flag = [...dangerDivs].find(x => x.innerText.includes('you need to confirm your email'));
  5768. let txt = dangerDivs[0].innerText;
  5769. if (flag) {
  5770. return shared.closeWithError(K.ErrorType.VERIFY_EMAIL, 'You need to verify your email address at the site. Go to ' + (new URL('settings', window.location)).href + ' to send the email.');
  5771. }
  5772. }
  5773. }
  5774. }
  5775. class CPUFaucet extends Faucet {
  5776. constructor() {
  5777. let elements = {
  5778. countdownMinutes: new CountdownWidget({selector: '#refilltimer', parser: Parsers.stormGainCountdown}), // <span id="refilltimer">00:47:19</span>
  5779. rollButton: new ButtonWidget({selector: '#enablebtncaptca'}),
  5780. balance: new ReadableWidget({selector: '#topcoins', parser: Parsers.trimNaNs}),
  5781. claimed: new ReadableWidget({selector: '#modal_header_msg', parser: Parsers.freeEthereumIoClaimed}),
  5782. captcha: new HCaptchaWidget(),
  5783. success: new ReadableWidget({selector: '#show_roll_numbers span'})
  5784. };
  5785. let actions = {
  5786. readRolledNumber: false,
  5787. preRun: false,
  5788. altValidation: true
  5789. };
  5790. super(elements, actions);
  5791. }
  5792. init() {
  5793. if (this._url.includes('/faucet')) {
  5794. // Pick faucet
  5795. // Faucet list: let abc = [...document.querySelectorAll('.faucet-list-item')].map(x => x.parentElement)
  5796. this.run();
  5797. return;
  5798. } else if (this._url.includes('/login')) {
  5799. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5800. return;
  5801. } else if (this._url.endsWith('_faucet')) {
  5802. // Click claim now
  5803. // Button might be: document.querySelector('.coinpayu-faucet-claim-msg button')
  5804. } else if (this._url.endsWith('/claim')) {
  5805. // Click to see captcha.. maybe: document.querySelector('.faucet-claim-box-button button')
  5806. // and good luck...
  5807. }
  5808. }
  5809. }
  5810. class Heli extends Faucet {
  5811. constructor() {
  5812. let elements = {
  5813. countdownMinutes: new CountdownWidget({selector: '#refilltimer', parser: Parsers.stormGainCountdown}), // <span id="refilltimer">00:47:19</span>
  5814. rollButton: new ButtonWidget({selector: '#enablebtncaptca'}),
  5815. balance: new ReadableWidget({selector: '#topcoins', parser: Parsers.trimNaNs}),
  5816. claimed: new ReadableWidget({selector: '#modal_header_msg', parser: Parsers.freeEthereumIoClaimed}),
  5817. captcha: new HCaptchaWidget(),
  5818. success: new ReadableWidget({selector: '#show_roll_numbers span'})
  5819. };
  5820. let actions = {
  5821. readRolledNumber: false,
  5822. preRun: false,
  5823. altValidation: true
  5824. };
  5825. super(elements, actions);
  5826. }
  5827. init() {
  5828. if (this._url.includes('/coins.php')) {
  5829. this.run();
  5830. return;
  5831. } else if (this._url.includes('/login.php')) {
  5832. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  5833. return;
  5834. }
  5835. }
  5836. isCountdownVisible() {
  5837. return this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly && this._elements.countdownMinutes.isUserFriendly.innerText != '00:00:00';
  5838. }
  5839. readClaimed() { // read from doc load function
  5840. shared.devlog(`@Heli readClaimed`);
  5841. let claimed = this._result.claimed ?? 0;
  5842. try {
  5843. let fLoad = document.body.onload;
  5844. if (fLoad) {
  5845. fLoad = fLoad.toString().split('Successfully claimed ');
  5846. if (fLoad.length > 0) {
  5847. fLoad = fLoad[1].split(' ');
  5848. shared.devlog(`@Heli readClaimed => ${fLoad[0]}`);
  5849. claimed = +fLoad[0];
  5850. }
  5851. }
  5852. } catch (err) {
  5853. shared.devlog(`@Heli readClaimed error: ${err}`);
  5854. }
  5855. return claimed;
  5856. }
  5857. }
  5858. class CBGRoll extends Faucet {
  5859. constructor() {
  5860. let elements = {
  5861. countdownMinutes: new CountdownWidget({selector: 'p.alert.alert-info', parser: Parsers.trimNaNs}),
  5862. // rollButton: new SubmitWidget({selector: '#wpbf-claim-form'}),
  5863. rollButton: new SubmitWidget({selector: '#wpbf-claim-form input[type="submit"]'}),
  5864. claimed: new ReadableWidget({selector: 'div.alert.alert-success', parser: Parsers.cbgClaimed}),
  5865. captcha: new HCaptchaWidget(),
  5866. addressInput: new TextboxWidget({ selector: '#wpbf_address' }),
  5867. success: new ReadableWidget({selector: 'div.alert.alert-success a[href="https://faucetpay.io/?r=2480995"]'})
  5868. };
  5869. let actions = {
  5870. readRolledNumber: false,
  5871. readClaimed: true,
  5872. readBalance: false,
  5873. preRun: true,
  5874. preSaveResult: true
  5875. };
  5876. super(elements, actions);
  5877. }
  5878. init() {
  5879. this._docType = (window != window.top ? 'IFRAME' : 'TOP');
  5880. shared.devlog(`@CBG init (${window.location.host}) => ${this._docType}`);
  5881. if (this._docType == 'IFRAME') {
  5882. this.run();
  5883. return;
  5884. } else if(this._docType == 'TOP' && window.location.host.includes('.cryptobaggiver.com')) {
  5885. // running iframe as top
  5886. this.run();
  5887. return;
  5888. } else {
  5889. //TODO: wait and close after claiming on the iframe
  5890. return;
  5891. }
  5892. }
  5893. async preRun() {
  5894. shared.devlog(`@CBG preRun`);
  5895. //TODO: fill INPUT ADDRESS
  5896. let dangerDivs = document.querySelectorAll('div.alert.alert-danger');
  5897. if (dangerDivs.length > 0) {
  5898. return shared.closeWithError(K.ErrorType.ERROR, dangerDivs[0].innerText);
  5899. }
  5900. if (this._elements.addressInput.isUserFriendly) {
  5901. if (this._elements.addressInput.value != shared.getCurrent().params.address) {
  5902. shared.devlog(`@CBG addressInput Found. Using ${shared.getCurrent().params.address}`);
  5903. this._elements.addressInput.value = shared.getCurrent().params.address;
  5904. } else {
  5905. shared.devlog(`@CBG addressInput already filled`);
  5906. }
  5907. } else {
  5908. shared.devlog(`@CBG addressInput not found`);
  5909. return this.preRun();
  5910. }
  5911. return true;
  5912. }
  5913. async detectAction() {
  5914. shared.devlog(`@CBGdetectAction Custom (${this._docType})`);
  5915. return wait().then( () => {
  5916. if ( this.isCountdownVisible() ) {
  5917. shared.devlog('needToWait');
  5918. return Promise.resolve({action: 'needToWait'});
  5919. } else if ( this.isRollButtonVisible() ) {
  5920. shared.devlog('doRoll');
  5921. return Promise.resolve({action: 'doRoll'});
  5922. } else if ( this._elements.success.isUserFriendly ) {
  5923. shared.devlog('Successful run');
  5924. return this.updateResult();
  5925. } else {
  5926. return this.detectAction();
  5927. }
  5928. });
  5929. }
  5930. clickRoll() {
  5931. try {
  5932. shared.devlog('Clicking roll button');
  5933. Element.prototype._addEventListener = Element.prototype.addEventListener;
  5934. Element.prototype.addEventListener = function () {
  5935. let args = [...arguments]
  5936. let temp = args[1];
  5937. args[1] = function () {
  5938. let args2 = [...arguments];
  5939. args2[0] = Object.assign({}, args2[0])
  5940. args2[0].isTrusted = true;
  5941. return temp(...args2);
  5942. }
  5943. return this._addEventListener(...args);
  5944. }
  5945. this._elements.rollButton.click();
  5946. this.validateRun();
  5947. // setTimeout(() => { this.validateRun() }, helpers.randomMs(10000, 12000));
  5948. } catch (err) {
  5949. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  5950. }
  5951. }
  5952. preSaveResult() {
  5953. if (this._docType == 'IFRAME') {
  5954. this._result.closeParentWindow = true;
  5955. } else if(this._docType == 'TOP' && window.location.host.includes('.cryptobaggiver.com')) {
  5956. this._result.closeParentWindow = true;
  5957. }
  5958. }
  5959. }
  5960. class G8 extends Faucet {
  5961. constructor() {
  5962. let elements = {
  5963. preRunButton: new ButtonWidget({selector: 'button[data-target="#captchaModal"]'}),
  5964. claimsLeft: new ReadableWidget({selector: '.alert.alert-info.fade.show', parser: Parsers.g8ClaimsLeft}),
  5965. rollButton: new ButtonWidget({selector: '#login'}),
  5966. claimed: new ReadableWidget({selector: '.alert.alert-success.fade.show', parser: Parsers.cbgClaimed}),
  5967. captcha: new HCaptchaWidget(),
  5968. success: new ReadableWidget({selector: '.alert.alert-success.fade.show'}),
  5969. addressInput: new TextboxWidget({ selector: '#address' }),
  5970. outOfFundsDivSelector: '.alert.alert-danger'
  5971. };
  5972. let actions = {
  5973. readTimeLeft: false,
  5974. readRolledNumber: false,
  5975. readClaimed: true,
  5976. readBalance: false,
  5977. preRun: true,
  5978. checkIfOutOfFunds: true
  5979. };
  5980. super(elements, actions);
  5981. }
  5982. init() {
  5983. shared.devlog(`@G8 init`);
  5984. this.run();
  5985. return;
  5986. }
  5987. async preRun() {
  5988. shared.devlog(`@G8 preRun`);
  5989. return wait().then( () => {
  5990. if (document.querySelectorAll('.alert.alert-danger.fade.show').length > 0) {
  5991. let divErrMsg = document.querySelectorAll('.alert.alert-danger.fade.show')[0].innerText;
  5992. shared.devlog(`@G8 Claim error message: ${divErrMsg}`);
  5993. if(divErrMsg != 'Session invalid, try again') {
  5994. shared.closeWithError(K.ErrorType.ERROR, divErrMsg);
  5995. return;
  5996. }
  5997. }
  5998. if(this._elements.claimsLeft.isUserFriendly) {
  5999. shared.devlog(`@G8 ClaimsLeft Check`);
  6000. try {
  6001. shared.devlog(`@G8 ClaimsLeft: ${this._elements.claimsLeft.value}`);
  6002. if (+this._elements.claimsLeft.value <= 0) {
  6003. shared.closeWithError(K.ErrorType.ERROR, 'No more claims left today');
  6004. return;
  6005. }
  6006. } catch (err) {
  6007. shared.devlog(`@G8 ClaimsLeft: error reading claims left: ${err}`);
  6008. }
  6009. }
  6010. if (this._elements.preRunButton.isUserFriendly) {
  6011. shared.devlog(`@preRunButton is userfriendly`);
  6012. if (this._elements.addressInput.isUserFriendly) {
  6013. if (this._elements.addressInput.value != shared.getCurrent().params.address) {
  6014. this._elements.addressInput.value = shared.getCurrent().params.address;
  6015. }
  6016. if (!this._elements.preRunButton.isUserFriendly.disabled) {
  6017. return this._elements.preRunButton.click();
  6018. }
  6019. }
  6020. }
  6021. return this.preRun();
  6022. });
  6023. }
  6024. async detectAction() {
  6025. shared.devlog(`@detectAction Custom`);
  6026. return wait().then( () => {
  6027. if ( this.isCountdownVisible() ) {
  6028. return Promise.resolve({action: 'needToWait'});
  6029. } else if ( this.isRollButtonVisible() ) {
  6030. return Promise.resolve({action: 'doRoll'});
  6031. } else if ( this._elements.success.isUserFriendly ) {
  6032. shared.devlog('Successful run');
  6033. return this.updateResult();
  6034. } else {
  6035. return this.detectAction();
  6036. }
  6037. });
  6038. }
  6039. }
  6040. class DutchyRoll extends Faucet {
  6041. constructor() {
  6042. let elements = {
  6043. countdownMinutes: new CountdownWidget({selector: '#timer', parser: Parsers.splitAndIdxToInt, options: { splitter: 'Minutes', idx: 0} }), // "26 Minutes 23"
  6044. captcha: new HCaptchaWidget(),
  6045. rollButton: new ButtonWidget({selector: '#claim'}), //w/booster video: '#unlockbutton'
  6046. success: new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse'}),
  6047. claimed: new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.freeEthereumIoClaimed}) //"You Won 0.00409070 TRX + 20 XP"
  6048. };
  6049. let actions = {
  6050. preRun: true,
  6051. readClaimed: true,
  6052. readBalance: false,
  6053. readRolledNumber: false
  6054. };
  6055. super(elements, actions);
  6056. }
  6057. init() {
  6058. switch(window.location.host) {
  6059. case 'autofaucet.dutchycorp.space':
  6060. if (this._url.includes('/roll.php')) {
  6061. this._elements.claimed = new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.dutchysClaimed})
  6062. } else if (this._url.includes('/login.php')) {
  6063. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  6064. return;
  6065. }
  6066. break;
  6067. case 'express.dutchycorp.space':
  6068. if (this._url.includes('/roll.php')) {
  6069. this._elements.claimed = new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.dutchysClaimed})
  6070. } else if (this._url.includes('/coin_roll.php')) {
  6071. this._elements.claimed = new ReadableWidget({selector: '.card.green.pulse p,.card.blue.pulse,.card.green.animated,.card.green.pulse', parser: Parsers.dutchysClaimedToFloat})
  6072. } else if (this._url.includes('/index.php')) {
  6073. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, 'You need to login using ExpressCrypto (EC-UserId-XXXXXX).');
  6074. return;
  6075. }
  6076. break;
  6077. }
  6078. this.run();
  6079. return;
  6080. }
  6081. async preRun() {
  6082. if (this._elements.captcha.isUserFriendly) {
  6083. return true;
  6084. } else {
  6085. return wait().preRun();
  6086. // if (document.readyState === 'complete') {
  6087. // shared.closeWithError(K.ErrorType.Error, `You need to set hCaptcha as default at ${(new URL('account.php', this._url)).href}`);
  6088. // } else {
  6089. // return wait().preRun();
  6090. // }
  6091. }
  6092. }
  6093. }
  6094. class FPB extends Faucet {
  6095. constructor(sitePrefix = null) {
  6096. let elements = {
  6097. rollButton: new ButtonWidget({selector: 'input[type="submit"][value="Claim From Faucet"]'}),
  6098. claimed: new ReadableWidget({selector: 'div.alert.alert-info', parser: Parsers.freeEthereumIoClaimed}),
  6099. captcha: new HCaptchaWidget(),
  6100. success: new ReadableWidget({selector: 'div.alert.alert-info'}),
  6101. login: {
  6102. inputUser: new TextboxWidget({ selector: 'input[name="user_name"]' }),
  6103. inputPass: new TextboxWidget({ selector: 'input[name="password"]' }),
  6104. rememberMe: new TextboxWidget({ selector: 'input[name="remember_me"]' }),
  6105. inputSubmit: new ButtonWidget({ selector: 'input[type="submit"][name="login"]' }),
  6106. setCredentials: false
  6107. },
  6108. outOfFundsDivSelector: '.alert.alert-info'
  6109. };
  6110. if(shared.getConfig()[sitePrefix + '.credentials.mode'] == 1) {
  6111. elements.login.setCredentials = {
  6112. username: shared.getConfig()[sitePrefix + '.credentials.username'],
  6113. password: shared.getConfig()[sitePrefix + '.credentials.password']
  6114. };
  6115. }
  6116. let actions = {
  6117. readClaimed: true,
  6118. readBalance: false,
  6119. readRolledNumber: false,
  6120. checkIfOutOfFunds: true
  6121. };
  6122. super(elements, actions);
  6123. }
  6124. init() {
  6125. if (this._url.includes('/dashboard')) {
  6126. this.run();
  6127. return;
  6128. } else if (this._url.includes('/login')) {
  6129. this.doLogin();
  6130. return;
  6131. }
  6132. }
  6133. async doLogin() {
  6134. shared.devlog(`@doLogin`);
  6135. return wait().then( () => {
  6136. if (!this._elements.login.inputUser.isUserFriendly || !this._elements.login.inputPass.isUserFriendly || !this._elements.login.inputSubmit.isUserFriendly) {
  6137. shared.devlog(`Waiting form inputs`);
  6138. return this.doLogin();
  6139. }
  6140. let loginErrorDiv = document.querySelector('div.alert.alert-info');
  6141. if (loginErrorDiv && loginErrorDiv.innerText.includes('not valid')) {
  6142. shared.closeWithError(K.ErrorType.LOGIN_ERROR, loginErrorDiv.innerText);
  6143. return;
  6144. }
  6145. if (this._elements.login.setCredentials != false) {
  6146. shared.devlog(`Setting credentials from var`);
  6147. this._elements.login.inputUser.value = this._elements.login.setCredentials.username;
  6148. this._elements.login.inputPass.value = this._elements.login.setCredentials.password;
  6149. }
  6150. try {
  6151. this._elements.login.rememberMe.isUserFriendly.checked = true;
  6152. } catch (err) {}
  6153. if (this._elements.login.inputUser.value != '' && this._elements.login.inputPass.value != '' ) {
  6154. shared.devlog(`@Run - Captcha`);
  6155. this._elements.captcha.isSolved().then(() => {
  6156. this._elements.login.inputSubmit.click();
  6157. return;
  6158. });
  6159. } else {
  6160. shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided');
  6161. return;
  6162. }
  6163. });
  6164. }
  6165. async detectAction() {
  6166. shared.devlog(`@detectAction Custom`);
  6167. return wait().then( () => {
  6168. if ( this.isCountdownVisible() ) {
  6169. shared.devlog('needToWait');
  6170. return Promise.resolve({action: 'needToWait'});
  6171. } else if ( this._elements.success.isUserFriendly ) {
  6172. shared.devlog('Successful run');
  6173. return this.updateResult();
  6174. } else if ( this.isRollButtonVisible() ) {
  6175. shared.devlog('doRoll');
  6176. return Promise.resolve({action: 'doRoll'});
  6177. } else {
  6178. return this.detectAction();
  6179. }
  6180. });
  6181. }
  6182. clickRoll() {
  6183. try {
  6184. shared.devlog(`@clickRoll custom`);
  6185. try {
  6186. window.scrollTo(0, document.body.scrollHeight);
  6187. this._elements.rollButton.scrollIntoView(false);
  6188. } catch (err) { }
  6189. this._elements.rollButton.click();
  6190. setTimeout( () => { this._elements.rollButton.click(); }, 5000);
  6191. // setTimeout(() => { this.validateRun() }, helpers.randomMs(10000, 12000));
  6192. } catch (err) {
  6193. shared.closeWithError(K.ErrorType.CLICK_ROLL_ERROR, err);
  6194. }
  6195. }
  6196. }
  6197. class VieRoll extends Faucet {
  6198. constructor() {
  6199. let elements = {
  6200. rollButton: new SubmitWidget({selector: '.main-content button[type="submit"]'}),
  6201. claimed: new ReadableWidget({selector: '.swal2-html-container', parser: Parsers.trimNaNs}),
  6202. captcha: new HCaptchaWidget(),
  6203. success: new ReadableWidget({selector: '.swal2-success-ring'}),
  6204. login: {
  6205. // captchaOptions: new SelectWidget({ selector: '#selectCaptcha', valueSeeked: 'hcaptcha' }),
  6206. inputUser: new TextboxWidget({ selector: '#email' }),
  6207. inputPass: new TextboxWidget({ selector: '#password' }),
  6208. // rememberMe: new TextboxWidget({ selector: 'input[name="remember_me"]' }),
  6209. inputSubmit: new SubmitWidget({ selector: 'button[type="submit"]' })
  6210. }
  6211. };
  6212. let actions = {
  6213. readClaimed: true,
  6214. readBalance: false,
  6215. readTimeLeft: false,
  6216. readRolledNumber: false,
  6217. preSaveResult: false,
  6218. preRun: true
  6219. };
  6220. super(elements, actions);
  6221. }
  6222. getClaimsQty() {
  6223. let statWidgets = document.querySelectorAll('.card.mini-stats-wid');
  6224. if (statWidgets.length < 4) return false;
  6225. let claimCounts = statWidgets[3].querySelector('p');
  6226. if (!claimCounts) return false;
  6227. claimCounts = claimCounts.innerText.split('/');
  6228. if (claimCounts.length != 2) return false;
  6229. return claimCounts[0];
  6230. }
  6231. async evalClaimsQty() {
  6232. let current = this.getClaimsQty();
  6233. if (current) {
  6234. current = +current;
  6235. } else {
  6236. return;
  6237. }
  6238. let previous = await shared.getProp('tempClaimsQty') || 0;
  6239. if (!isNaN(previous)) previous = +previous;
  6240. if (current == previous) {
  6241. return;
  6242. } else if (current < previous) {
  6243. return this.updateResult();
  6244. } else {
  6245. await shared.setProp('tempClaimsQty', current);
  6246. }
  6247. }
  6248. readClaimed() {
  6249. let claimed = 0.12;
  6250. try {
  6251. claimed = +document.querySelectorAll('.card.mini-stats-wid')[2].querySelector('p').innerText.split(' ')[0];
  6252. } catch (err) { }
  6253. return claimed;
  6254. }
  6255. async init() {
  6256. await this.evalClaimsQty();
  6257. if (window.location.pathname.includes('/faucet')) {
  6258. shared.devlog(`@VieRoll => At Faucet starting claim`);
  6259. this.run();
  6260. return;
  6261. } else if (window.location.pathname.includes('/firewall')) {
  6262. shared.devlog(`@VieRoll => At Firewall`);
  6263. this.solveFirewall();
  6264. return;
  6265. } else if (window.location.pathname.includes('/dashboard')) {
  6266. shared.devlog(`@VieRoll => At Dashboard`);
  6267. window.location.href = (new URL('faucet', window.location)).href;
  6268. return;
  6269. } else if (window.location.pathname == '/') {
  6270. // At home => go to login
  6271. let loginBtn = document.querySelector('.btn.btn-success');
  6272. if (loginBtn) {
  6273. loginBtn.click();
  6274. return;
  6275. } else {
  6276. shared.devlog(`@VieRoll => Home => Login button not found`);
  6277. window.location.href = (new URL('login', window.location)).href;
  6278. }
  6279. return;
  6280. } else if (this._url.includes('/login')) {
  6281. shared.devlog(`@VieRoll => At Login`);
  6282. let credentialsMode = this._params.credentials.mode;
  6283. switch(credentialsMode) {
  6284. case -1:
  6285. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, 'Manual login required.');
  6286. break;
  6287. case 0:
  6288. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, 'Login required and autologin is not configured.');
  6289. break;
  6290. default:
  6291. shared.devlog(`@VieRoll: Login attempt`);
  6292. this.doLogin();
  6293. break;
  6294. }
  6295. return;
  6296. }
  6297. }
  6298. async preRun() {
  6299. shared.devlog(`@preRun`);
  6300. return;
  6301. }
  6302. async solveFirewall() {
  6303. this.closeSwal();
  6304. this._elements.captcha.isSolved().then(() => {
  6305. let btn = new SubmitWidget({selector: 'form:not(.p-3) button[type="submit"]'});
  6306. btn.click();
  6307. });
  6308. }
  6309. async doLogin() {
  6310. shared.devlog(`@doLogin`);
  6311. return wait().then( () => {
  6312. if (!this._elements.login.inputUser.isUserFriendly || !this._elements.login.inputPass.isUserFriendly || !this._elements.login.inputSubmit.isUserFriendly) {
  6313. shared.devlog(`Waiting form inputs`);
  6314. return this.doLogin();
  6315. }
  6316. let loginErrorDiv = document.querySelector('div.alert.alert-danger');
  6317. if (loginErrorDiv) {
  6318. shared.closeWithError(K.ErrorType.LOGIN_ERROR, loginErrorDiv.innerText);
  6319. return;
  6320. }
  6321. if (this._params.credentials.mode == 1) {
  6322. shared.devlog(`Setting credentials`);
  6323. this._elements.login.inputUser.value = this._params.credentials.username;
  6324. this._elements.login.inputPass.value = this._params.credentials.password;
  6325. }
  6326. if (this._elements.login.inputUser.value != '' && this._elements.login.inputPass.value != '' ) {
  6327. this._elements.captcha.isSolved().then(() => {
  6328. this._elements.login.inputSubmit.click();
  6329. return;
  6330. });
  6331. } else {
  6332. shared.closeWithError(K.ErrorType.LOGIN_ERROR, 'No credentials were provided');
  6333. return;
  6334. }
  6335. });
  6336. }
  6337. preSaveResult() {
  6338. this.closeSwal();
  6339. }
  6340. closeSwal() {
  6341. let okButton = document.querySelector('button.swal2-confirm');
  6342. if (okButton) {
  6343. okButton.click();
  6344. }
  6345. }
  6346. }
  6347. class GRCRoll extends Faucet {
  6348. constructor() {
  6349. let elements = {
  6350. countdownMinutes: new CountdownWidget({selector: '#roll_wait_text', parser: Parsers.freeGrcCountdown}),
  6351. rollButton: new ButtonWidget({selector: 'input[id="roll_button"]'}),
  6352. balance: new ReadableWidget({selector: '#balance', parser: Parsers.trimNaNs}),
  6353. claimed: new ReadableWidget({selector: '#roll_comment .won', parser: Parsers.trimNaNs}),
  6354. rolledNumber: new ReadableWidget({selector: '#roll_result', parser: Parsers.trimNaNs}),
  6355. captcha: new NoCaptchaWidget({selector: '#roll_button'}),
  6356. success: new ReadableWidget({selector: '#roll_result'})
  6357. };
  6358. let actions = {
  6359. readTimeLeft: true,
  6360. readRolledNumber: true
  6361. };
  6362. super(elements, actions);
  6363. }
  6364. init() {
  6365. if (this._url.includes('#free_roll')) {
  6366. if (document.querySelectorAll('a[href="#login"]').length > 0) {
  6367. shared.closeWithError(K.ErrorType.NEED_TO_LOGIN, '');
  6368. return;
  6369. } else {
  6370. this.run();
  6371. return;
  6372. }
  6373. } else {
  6374. return;
  6375. }
  6376. }
  6377. isCountdownVisible() {
  6378. return this._elements.countdownMinutes && this._elements.countdownMinutes.isUserFriendly && this._elements.countdownMinutes.isUserFriendly.innerText != '';
  6379. }
  6380. }
  6381. class O24Roll extends Faucet {
  6382. constructor() {
  6383. let elements = {
  6384. claimed: new ReadableWidget({selector: '#roll_comment .won', parser: Parsers.trimNaNs})
  6385. };
  6386. let actions = {
  6387. readTimeLeft: true,
  6388. readRolledNumber: false,
  6389. readBalance: false
  6390. };
  6391. super(elements, actions);
  6392. }
  6393. init() {
  6394. if (this.isCountdownVisible() || this.readClaimed() != 0) {
  6395. this.updateResult();
  6396. return;
  6397. }
  6398. this.solve();
  6399. }
  6400. getSpotsAvailable() {
  6401. try {
  6402. let elm = document.querySelector('.pos.pfree a');
  6403. if (elm) {
  6404. return elm.innerText.split('$')[1].split('-')[0];
  6405. } else {
  6406. shared.devlog(`Unable to find spots sold elm`);
  6407. return;
  6408. }
  6409. } catch (err) {
  6410. shared.devlog(`Unable to read spots sold`);
  6411. shared.devlog(err);
  6412. }
  6413. }
  6414. isPrime(num) {
  6415. for(var i = 2; i < num; i++){
  6416. if(num % i === 0){
  6417. return false;
  6418. }
  6419. }
  6420. return num > 1;
  6421. }
  6422. async solve() {
  6423. let spotsAvailable = this.getSpotsAvailable();
  6424. if(!spotsAvailable) {
  6425. // close with error
  6426. shared.devlog(`Could not find spots available`);
  6427. this.updateResult();
  6428. return;
  6429. }
  6430. let numbers = [...document.querySelectorAll('select[name="pr"] option[value]')].map(x => x.innerText)
  6431. let prime = numbers.find(x => {
  6432. return this.isPrime(x)
  6433. });
  6434. if(!prime) {
  6435. // close with error
  6436. shared.devlog(`Could not find prime number`);
  6437. this.updateResult();
  6438. return;
  6439. }
  6440. // fill address
  6441. let addrInput = document.querySelector('label input[name="a"]');
  6442. if (addrInput) {
  6443. addrInput.value = this._params.address;
  6444. } else {
  6445. shared.devlog(`Could not find address input element`);
  6446. this.updateResult();
  6447. return;
  6448. }
  6449. await wait(helpers.randomInt(1500, 3000));
  6450. // answer_1:
  6451. document.querySelector('select[name="tt"]').value=(+spotsAvailable-1).toString()
  6452. await wait(helpers.randomInt(400, 5000));
  6453. // answer_2:
  6454. let primeSelect = document.querySelector('select[name="pr"]');
  6455. helpers.triggerMouseEvent (primeSelect, "mouseenter");
  6456. await wait(helpers.randomInt(5600, 29000));
  6457. helpers.triggerMouseEvent (primeSelect, "mouseout");
  6458. primeSelect.value=prime.toString()
  6459. await wait(helpers.randomInt(1500, 5000));
  6460. let claimForm = document.querySelector('form');
  6461. if(claimForm) {
  6462. claimForm.submit();
  6463. }
  6464. }
  6465. isCountdownVisible() {
  6466. let pars = [...document.querySelectorAll('p')];
  6467. if (pars.find(x => x.innerText.includes('please wait until next day'))) {
  6468. // need to wait a day
  6469. return true;
  6470. }
  6471. if (pars.find(x => x.innerText.includes('PROBLEM'))) {
  6472. // need to wait at least 5 min
  6473. return true;
  6474. }
  6475. return false;
  6476. }
  6477. readClaimed() {
  6478. let pars = [...document.querySelectorAll('p')];
  6479. let claimedElm = pars.find(x => x.innerText.includes('been transferred to your account'));
  6480. if (claimedElm) {
  6481. return claimedElm.innerText.split(' ')[0];
  6482. } else {
  6483. return 0;
  6484. }
  6485. }
  6486. readNextRoll() {
  6487. try {
  6488. let pars = [...document.querySelectorAll('p')];
  6489. if (pars.find(x => x.innerText.includes('PROBLEM'))) {
  6490. // need to wait
  6491. return helpers.addMinutes(helpers.randomInt(6, 22));
  6492. }
  6493. if (pars.find(x => x.innerText.includes('ALL DAILY CLAIMS') || x.innerText.includes('You have 0 claims left'))) {
  6494. // need to wait a day
  6495. return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160));
  6496. }
  6497. if (pars.find(x => x.innerText.includes('You have'))) {
  6498. // need to wait a day
  6499. return helpers.addMinutes(helpers.randomInt(6, 22));
  6500. }
  6501. } catch (err) { shared.devlog(`@readNextRoll: ${err}`); }
  6502. //return helpers.addMinutes(60);
  6503. return helpers.addMinutes(60 * 24 + helpers.randomInt(10, 160));
  6504. }
  6505. }
  6506. // TODO: refactor => separate in PTC and FAUCET, using a generic PTC class with PTCList, PTCSingle, etc
  6507. // create a container class that has both PTC and FAUCET
  6508. class FCryptoRoll extends Faucet {
  6509. constructor() {
  6510. let elements = {
  6511. countdownMinutes: new CountdownWidget({selector: '.sidebar-links .cursor-not-allowed span.notranslate', parser: Parsers.splitAndIdxToInt, options: { splitter: ':', idx: 1} }), // '00:21:28'
  6512. rollButton: new ButtonWidget({selector: 'button.notranslate.inline-flex.items-center.text-center:not(.hidden)'}),
  6513. balance: new ReadableWidget({selector: 'div.flex.badge.text-bg-yellow', parser: Parsers.trimNaNs}), // '405.81 Coins'
  6514. claimed: new ReadableWidget({selector: 'div.ml-3.w-0 p span.text-yellow-500.font-medium', parser: Parsers.splitAndIdxTrimNaNs, options: { splitter: '(', idx: 0} }), // '25.05 Coins (12 + 13.05)'
  6515. captcha: new HCaptchaWidget({selector: '#hcap-script > iframe'}),
  6516. success: new ReadableWidget({selector: 'div.ml-3.w-0 p span.text-yellow-500.font-medium'})
  6517. };
  6518. let actions = {
  6519. isMultiClaim: true,
  6520. preRoll: true,
  6521. postRun: true,
  6522. // altValidation: true,
  6523. readRolledNumber: false,
  6524. // updateWithoutClosing: true
  6525. };
  6526. super(elements, actions);
  6527. this._paths = {
  6528. faucet: '/task/faucet-claim',
  6529. // ptcList: '/ptc/list',
  6530. // ptcSingleStart: '/task/ptc-advertisement',
  6531. // ptcSingleWait: '/ptc/view',
  6532. dashboard: '/dashboard'
  6533. };
  6534. this._linkSelectors = {
  6535. Faucet: 'a[href="https://faucetcrypto.com/task/faucet-claim"]'
  6536. // PtcList: 'a[href="https://faucetcrypto.com/ptc/list"]',
  6537. // Shortlinks: 'a[href="https://faucetcrypto.com/shortlink/list"]',
  6538. // Challenges: 'a[href="https://faucetcrypto.com/challenge/list"]'
  6539. }
  6540. this.useUrlListener();
  6541. }
  6542. init() {
  6543. this._elements.captcha = new HCaptchaWidget({selector: '#hcap-script > iframe'});
  6544. this._elements.rollButton = new ButtonWidget({selector: 'button.notranslate.inline-flex.items-center.text-center:not(.hidden)'});
  6545. if (this._url.endsWith(this._paths.dashboard)) {
  6546. shared.devlog(`@FC => @dashboard`);
  6547. return this.runDashboard();
  6548. } else if (this._url.includes(this._paths.faucet)) {
  6549. shared.devlog(`@FC => @faucet`);
  6550. return wait().then( () => { this.run(); });
  6551. // } else if (this._url.endsWith(this._paths.ptcList)) {
  6552. // shared.devlog(`@FC => @ptcList`);
  6553. // return wait().then( () => { this.runPtcList(); });
  6554. // } else if (this._url.includes(this._paths.ptcSingleStart)) {
  6555. // shared.devlog(`@FC => PTC Single Step 1`);
  6556. // return wait().then( () => { this.runPtcSingleStart(); });
  6557. // } else if (this._url.includes(this._paths.ptcSingleWait)) {
  6558. // shared.devlog(`@FC => PTC Single Step 2`);
  6559. // return wait().then( () => { this.runPtcSingleWait(); });
  6560. }
  6561. shared.devlog(`@FC => No url match!`);
  6562. return;
  6563. }
  6564. readSections() {
  6565. let sections = {};
  6566. try {
  6567. for (var l in this._linkSelectors) {
  6568. sections[l] = {};
  6569. sections[l].elm = document.querySelector(this._linkSelectors[l]);
  6570. if (sections[l].elm) {
  6571. let qty = sections[l].elm.querySelector('span.ml-auto');
  6572. sections[l].qty = (qty && !isNaN(qty.innerText)) ? qty.innerText : 0;
  6573. }
  6574. }
  6575. } catch {}
  6576. this.sections = sections;
  6577. }
  6578. runDashboard() {
  6579. this.readSections();
  6580. if (this.sections['Faucet'].elm) {
  6581. shared.devlog(`@FC => goto faucet`);
  6582. this.sections['Faucet'].elm.click();
  6583. return;
  6584. } else {
  6585. // process Faucet results?
  6586. shared.devlog(`@FC => processing faucet results`);
  6587. return wait().then( () => { this.run(); });
  6588. }
  6589. }
  6590. // TODO: refactor and move
  6591. scrollTo() {
  6592. let mainContainer = document.querySelector('main');
  6593. if (mainContainer) {
  6594. mainContainer.scrollTo(0, mainContainer.scrollHeight - mainContainer.offsetHeight);
  6595. }
  6596. }
  6597. preRoll() { // search for 'You don't need to solve any captcha! The system is telling me that you are a good person :)'
  6598. this.scrollTo();
  6599. let checkCircleSpan = document.querySelector('p.justify-center span.text-green-500 svg.feather-check-circle');
  6600. if(checkCircleSpan) {
  6601. if (checkCircleSpan.parentElement.parentElement.innerText.toLowerCase().includes('the system is telling me that you are a good person')) {
  6602. shared.devlog(`No captcha needed`);
  6603. this._elements.captcha = new NoCaptchaWidget({selector: 'button.notranslate.inline-flex.items-center.text-center:not(.hidden):not(.cursor-not-allowed)'});
  6604. return;
  6605. }
  6606. }
  6607. }
  6608. postRun() {
  6609. shared.devlog(`@FC @postRun in ${window.location.href}`);
  6610. // if ( this._url.endsWith(this._paths.dashboard) || (this._oldClaimed && this._result && this._result.claimed && this._oldClaimed != this._result.claimed) ) {
  6611. if (this._url.endsWith(this._paths.dashboard) || this._oldClaimed != this._result.claimed) {
  6612. shared.devlog(`@FC @postRun => Claim/Action finished [${this._oldClaimed} != ${this._result.claimed}]`);
  6613. try {
  6614. this._elements.claimed.isUserFriendly.parentElement.parentElement.parentElement.querySelector('button');
  6615. shared.devlog(`@FC @postRun => closing claimed notification`);
  6616. } catch (err) {
  6617. shared.devlog(`@FC @postRun => error closing claimed notification: ${err}`);
  6618. }
  6619. this._oldClaimed = null;
  6620. this.readSections();
  6621. if (this.sections != {}) {
  6622. if (this.sections['Faucet'].elm) {
  6623. shared.devlog(`@FC @postRun => goto faucet`);
  6624. this.sections['Faucet'].elm.click();
  6625. return;
  6626. // } else if (this.sections['PtcList'].elm && this.sections['PtcList'].qty > 0) {
  6627. // shared.devlog(`@FC @postRun => has PTCs. goto ptcList`);
  6628. // this.sections['PtcList'].elm.click();
  6629. // return;
  6630. } else {
  6631. shared.devlog(`@FC @postRun => ignoring @1`);
  6632. }
  6633. } else {
  6634. shared.devlog(`@FC @postRun => ignoring @2`);
  6635. }
  6636. } else {
  6637. shared.devlog(`@FC @postRun => ignoring @3`);
  6638. }
  6639. this._result = shared.getProp('tempResults');
  6640. shared.closeWindow(this._result);
  6641. return;
  6642. }
  6643. async runPtcList() {
  6644. shared.devlog(`@FC => @runPtcList`);
  6645. let listItems = [...document.querySelectorAll('.grid.grid-responsive-3 .feather.feather-eye')].map(x => x.parentElement.parentElement).filter(x => x.isUserFriendly());
  6646. if (listItems.length > 0) {
  6647. shared.devlog(`@FC => goto PtcSingleStart`);
  6648. listItems[0].click();
  6649. return;
  6650. } else {
  6651. shared.devlog(`@FC => list invalid. Length: ${listItems.length}`);
  6652. return wait().then( () => { this.runPtcList() } );
  6653. }
  6654. }
  6655. runPtcSingleStart() {
  6656. shared.devlog(`@FC => @runPtcSingleStart`);
  6657. return this.run('doRoll');
  6658. }
  6659. runPtcSingleWait() {
  6660. shared.devlog(`@FC => @runPtcSingleWait`);
  6661. this._elements.captcha = new NoCaptchaWidget({selector: 'a.notranslate:not(.cursor-not-allowed)' });
  6662. this._elements.rollButton = new ButtonWidget({selector: 'a.notranslate:not(.cursor-not-allowed)' });
  6663. return this.run('doRoll');
  6664. }
  6665. }
  6666. let timer, landing;
  6667. let useTimer;
  6668. async function init() {
  6669. persistence = objectGenerator.createPersistence();
  6670. shared = objectGenerator.createShared();
  6671. useTimer = shared.getConfig()['defaults.extraInterval'];
  6672. if (window.location.host === 'criptologico.com') {
  6673. landing = window.location.host;
  6674. timer = new Timer(true, 30);
  6675. shared.devlog('Manager Reloaded');
  6676. manager = objectGenerator.createManager();
  6677. CFPromotions = objectGenerator.createCFPromotions();
  6678. ui = objectGenerator.createUi();
  6679. CFHistory = objectGenerator.createCFHistory();
  6680. await manager.init();
  6681. } else {
  6682. detectWeb();
  6683. }
  6684. }
  6685. init();
  6686. })();

comments powered by Disqus