├── .gitignore ├── package.json ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "berachain-faucet-taker", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cheerio": "^1.0.0-rc.12", 14 | "colors": "^1.4.0", 15 | "cron": "^3.1.6", 16 | "puppeteer": "^21.7.0", 17 | "puppeteer-extra-plugin-adblocker": "^2.13.6", 18 | "puppeteer-extra-plugin-stealth": "^2.11.2", 19 | "readline-sync": "^1.4.10" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Berachain-Faucet-Taker 2 | 3 | This Node.js script automates interactions with the Berachain faucet website using Puppeteer. It navigates through the site to accept terms, enter a wallet address, and assess success or error messages. Based on the outcome, it schedules a Cron job to retry the process every 8 hours. The script is tailored for both local environments and VPS deployment. 4 | 5 | ## Installation 6 | 7 | Before running the script, ensure Node.js is installed on your machine. To install the required packages, navigate to the root directory of the project and run: 8 | 9 | ```bash 10 | git clone https://github.com/dante4rt/Berachain-Faucet-Taker.git && cd Berachain-Faucet-Taker && npm install 11 | ``` 12 | 13 | This command will install Puppeteer, Cron, readline-sync, and colors, which are necessary for the script to function correctly. 14 | 15 | ## Additional Dependencies for VPS 16 | 17 | If you're running this script on a VPS, you might need to install additional dependencies for Puppeteer. On a Debian-based system (like Ubuntu), execute the following: 18 | 19 | ```bash 20 | sudo apt-get update 21 | sudo apt-get install -y gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \ 22 | libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \ 23 | libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 \ 24 | libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \ 25 | ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget libgbm1 26 | ``` 27 | 28 | ## Usage 29 | 30 | To run the script, execute the following command in your terminal: 31 | 32 | ```bash 33 | node index.js 34 | ``` 35 | 36 | You will be prompted to enter a wallet address. The script will then perform actions on the faucet website and provide output in the console. 37 | 38 | ## Features 39 | 40 | - **Puppeteer Automation**: Manages browser interactions to navigate and interact with web pages. 41 | - **Cron Scheduling**: Schedules tasks to be executed repeatedly at specified intervals using the `cron` package. 42 | - **Readline Sync**: Dynamically accepts wallet address input from the command line. 43 | - **Colored Console Logs**: Enhances output readability with colored console logs. 44 | 45 | ## Notes 46 | 47 | - The script runs in headless mode on VPS for efficient operation. 48 | - Ensure compliance with the website's terms of service when using this script. 49 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer'); 2 | const { CronJob } = require('cron'); 3 | const readlineSync = require('readline-sync'); 4 | require('colors'); 5 | 6 | function checkWebsite(address, callback) { 7 | puppeteer 8 | .launch({ 9 | headless: 'new', 10 | args: ['--no-sandbox', '--disable-setuid-sandbox'], 11 | }) 12 | .then((browser) => { 13 | browser.newPage().then((page) => { 14 | page.goto('https://artio.faucet.berachain.com/').then(() => { 15 | const termsCheckboxSelector = '#terms'; 16 | page.waitForSelector(termsCheckboxSelector).then(() => { 17 | page.click(termsCheckboxSelector).then(() => { 18 | const agreeButtonSelector = 19 | '//button[contains(text(), "I AGREE")]'; 20 | page.waitForXPath(agreeButtonSelector).then(() => { 21 | page.$x(agreeButtonSelector).then((agreeButtons) => { 22 | if (agreeButtons.length > 0) { 23 | agreeButtons[0].click().then(() => { 24 | const addressInputSelector = 25 | 'body > div:nth-child(12) > div.relative.flex.min-h-screen.w-full.flex-col.overflow-hidden.bg-background > main > div > div.flex.w-full.flex-col-reverse.items-center.justify-between.py-12.xl\\:flex-row > div > div.flex.flex-col.gap-1 > div.relative > div > input'; 26 | page.waitForSelector(addressInputSelector).then(() => { 27 | page.type(addressInputSelector, address).then(() => { 28 | const buttonSelector = 29 | 'body > div:nth-child(12) > div.relative.flex.min-h-screen.w-full.flex-col.overflow-hidden.bg-background > main > div > div.flex.w-full.flex-col-reverse.items-center.justify-between.py-12.xl\\:flex-row > div > button'; 30 | page.waitForSelector(buttonSelector).then(() => { 31 | page.click(buttonSelector).then(() => { 32 | page.waitForTimeout(3000).then(() => { 33 | page.click(buttonSelector).then(() => { 34 | page 35 | .waitForSelector('div[role="alert"]', { 36 | timeout: 5000, 37 | }) 38 | .then(() => { 39 | page 40 | .$( 41 | 'div[role="alert"].border-destructive-foreground' 42 | ) 43 | .then((errorElement) => { 44 | if (errorElement) { 45 | page 46 | .evaluate( 47 | (el) => el.textContent, 48 | errorElement 49 | ) 50 | .then((errorMessage) => { 51 | console.log( 52 | 'Error: '.red + 53 | errorMessage.red 54 | ); 55 | browser.close(); 56 | callback('error'); 57 | }); 58 | } else { 59 | page 60 | .$( 61 | 'div[role="alert"].border-success-foreground' 62 | ) 63 | .then((successElement) => { 64 | if (successElement) { 65 | page 66 | .evaluate( 67 | (el) => el.textContent, 68 | successElement 69 | ) 70 | .then((successMessage) => { 71 | console.log( 72 | 'Success: '.green + 73 | successMessage.green 74 | ); 75 | browser.close(); 76 | callback('success'); 77 | }); 78 | } else { 79 | browser.close(); 80 | callback('none'); 81 | } 82 | }); 83 | } 84 | }) 85 | .catch(() => { 86 | browser.close(); 87 | callback('none'); 88 | }); 89 | }); 90 | }); 91 | }); 92 | }); 93 | }); 94 | }); 95 | }); 96 | }); 97 | } 98 | }); 99 | }); 100 | }); 101 | }); 102 | }); 103 | }); 104 | }); 105 | } 106 | 107 | function scheduleCronJob(address) { 108 | const job = new CronJob('0 */8 * * *', () => { 109 | console.log('Running cron job'.yellow); 110 | checkWebsite(address, (status) => { 111 | console.log('Status:'.yellow, status.yellow); 112 | }); 113 | }); 114 | 115 | job.start(); 116 | console.log('Cron job scheduled'.blue); 117 | } 118 | 119 | const address = readlineSync.question('Enter the wallet address: '.cyan); 120 | 121 | checkWebsite(address, (status) => { 122 | console.log('Initial status:'.cyan, status.cyan); 123 | if (status !== 'none') { 124 | scheduleCronJob(address); 125 | } 126 | }); 127 | --------------------------------------------------------------------------------