├── .dockerignore ├── .gitignore ├── Dockerfile ├── Jenkinsfile ├── README.md ├── TODO.md ├── package.json ├── puppeteer.ico ├── record └── screen_shots │ ├── bestbuy │ └── sample.png │ ├── gamestop │ └── sample.png │ ├── microcenter │ └── sample.png │ ├── newegg │ └── sample.png │ ├── target │ └── sample.png │ └── walmart │ └── sample.png ├── scripts ├── bestbuy │ ├── bestbuy-bot.js │ ├── build.sh │ ├── myInfo.js │ ├── taskHandler.js │ ├── user_info │ │ └── .env.userInfo │ └── utils.js ├── gamestop │ ├── build.sh │ ├── gamestop-bot.js │ ├── myInfo.js │ ├── taskHandler.js │ ├── user_info │ │ └── .env.userInfo │ └── utils.js ├── microcenter │ ├── README.md │ ├── build.sh │ ├── micro-bot.js │ ├── myInfo.js │ ├── taskHandler.js │ ├── user_info │ │ └── .env.userInfo │ └── utils.js ├── newegg │ ├── README.md │ ├── build.sh │ ├── myInfo.js │ ├── newegg-bot.js │ ├── taskHandler.js │ ├── user_info │ │ └── .env.userInfo │ └── utils.js ├── target │ ├── build.sh │ ├── myInfo.js │ ├── target-bot.js │ ├── taskHandler.js │ ├── user_info │ │ └── .env.userInfo │ └── utils.js ├── test │ ├── all-bots-find-stocks.test.sh │ ├── all-bots-full-cycle.test.sh │ ├── bestbuy-bot.test.sh │ ├── bestbuy-find-stocks.test.sh │ ├── gamestop-bot.test.sh │ ├── gamestop-find-stocks.test.sh │ ├── micro-bot.test.sh │ ├── micro-find-stocks.test.sh │ ├── newegg-bot.test.sh │ ├── newegg-find-stocks.test.sh │ ├── target-bot.test.sh │ ├── target-find-stocks.test.sh │ ├── walmart-bot.test.sh │ └── walmart-find-stocks.test.sh └── walmart │ ├── build.sh │ ├── myInfo.js │ ├── taskHandler.js │ ├── user_info │ └── .env.userInfo │ ├── utils.js │ └── walmart-bot.js └── youtube-example.js /.dockerignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | *.vscode 3 | *debug.log 4 | *desktop.ini 5 | .env.dev 6 | node_modules -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | !sample.png 3 | *node_modules 4 | npm-debug.log 5 | .idea 6 | *.vscode 7 | *debug.log 8 | *desktop.ini 9 | vncconfig.sh 10 | # Include your .evn file here 11 | #.env.userInfo 12 | .env.dev 13 | *.DS_Store 14 | package-lock.json 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # This Dockerfile is used to build an headles vnc image based on Ubuntu 2 | FROM consol/ubuntu-xfce-vnc 3 | 4 | USER root 5 | 6 | # Setting env 7 | ENV VNC_RESOLUTION=1920x1080 \ 8 | VNC_PW=puppeteer \ 9 | PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ 10 | PUPPETEER_EXEC_PATH=google-chrome-stable 11 | 12 | # Create app directory 13 | WORKDIR /usr/src/app 14 | 15 | COPY . ./ 16 | # update, install puppeteer dependencies, and install node 17 | RUN apt-get update -y \ 18 | && apt-get install libgconf-2-4 sudo curl wget xvfb dos2unix apt-transport-https ca-certificates -y \ 19 | && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ 20 | && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ 21 | && apt-get update -y \ 22 | && apt-get install google-chrome-stable --no-install-recommends -y 23 | #&& rm -rf /var/lib/apt/lists/* 24 | 25 | RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - \ 26 | && sudo apt-get install nodejs -y \ 27 | && node -v \ 28 | && npm -v 29 | RUN find . -type f -name "*.sh" -exec dos2unix {} \+; 30 | 31 | RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo \ 32 | && useradd -m jenkins && echo "jenkins:jenkins" | chpasswd && adduser jenkins sudo 33 | 34 | RUN whoami 35 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | 3 | node { 4 | if (env.BRANCH_NAME.startsWith('PR')) { 5 | return; 6 | } 7 | 8 | def image; 9 | def currentStage; 10 | def entryPoint = '-it'; 11 | try { 12 | stage('Cleanup and Checkout') { 13 | sh("echo Branch_name:${env.BRANCH_NAME}"); 14 | cleanWs(); 15 | checkout([ 16 | $class: 'GitSCM', 17 | branches: [[name: "${env.BRANCH_NAME}"]], 18 | doGenerateSubmoduleConfigurations: false, 19 | extensions: [], 20 | submoduleCfg: [], 21 | userRemoteConfigs: [[credentialsId: 'Yorisoft', url: 'https://github.com/Yorisoft/puppet-purchase']] 22 | ]) 23 | } 24 | 25 | currentStage = 'Build Image'; 26 | stage(currentStage) { 27 | image = docker.build('puppet-purchase') 28 | } 29 | 30 | currentStage = 'Install npm'; 31 | stage(currentStage) { 32 | image.inside(entryPoint) { 33 | sh('npm install'); 34 | //sh ('npm i puppeteer --save'); 35 | sh('npm -v'); 36 | } 37 | } 38 | 39 | // currentStage = 'bestuy-bot-test'; 40 | // stage(currentStage) { 41 | // image.inside(entryPoint) { 42 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_BESTBUY', variable: 'TEST_USER_LISTING_URL'), 43 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 44 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 45 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 46 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 47 | // ]) { 48 | // try{ 49 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr.txt"); //prints to test file (nick) 50 | // sh('npm run bestbuy-bot-test') 51 | // } catch (err){ 52 | // echo err.getMessage() 53 | // throw err 54 | 55 | // } 56 | // } 57 | // } 58 | // } 59 | 60 | // currentStage = 'target-bot-test'; 61 | // stage(currentStage) { 62 | // image.inside(entryPoint) { 63 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_TARGET', variable: 'TEST_USER_LISTING_URL'), 64 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 65 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 66 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 67 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 68 | // ]) { 69 | // try{ 70 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr1.txt"); 71 | // sh('npm run target-bot-test'); 72 | // } catch (err){ 73 | // echo err.getMessage() 74 | // throw err 75 | // } 76 | // } 77 | // } 78 | // } 79 | 80 | parallel( 81 | // My test user or ip keeps getting temporarily banned. Need solution for testing.. 82 | "bestuy-bot-test": { 83 | image.inside(entryPoint) { 84 | withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_BESTBUY', variable: 'TEST_USER_LISTING_URL'), 85 | string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 86 | string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 87 | string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 88 | string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 89 | ]) { 90 | try{ 91 | //echo("echo $TEST_USER_URL > $WORKSPACE/grr.txt"); //prints to test file (nick) 92 | sh('npm run bestbuy-bot-test') 93 | } 94 | catch (err){ 95 | echo err.getMessage() 96 | throw err 97 | 98 | } 99 | } 100 | } 101 | } 102 | 103 | // "target-bot-test": { 104 | // image.inside(entryPoint) { 105 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_TARGET', variable: 'TEST_USER_LISTING_URL'), 106 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 107 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 108 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 109 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 110 | // ]) { 111 | // try{ 112 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr1.txt"); 113 | // sh('npm run target-bot-test'); 114 | // } 115 | // catch (err){ 116 | // echo err.getMessage() 117 | // throw err 118 | // } 119 | // } 120 | // } 121 | // } 122 | 123 | // "gamestop-bot-test": { 124 | // image.inside(entryPoint) { 125 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_GAMESTOP', variable: 'TEST_USER_LISTING_URL'), 126 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 127 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 128 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL_PASSW', variable: 'TEST_USER_INBOX_PASSW'), 129 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 130 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 131 | // ]) { 132 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr3.txt"); 133 | // sh('npm run gamestop-bot-test'); 134 | // } 135 | // } 136 | // }, 137 | 138 | // "micro-bot-test": { 139 | // image.inside(entryPoint) { 140 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_MICRO', variable: 'TEST_USER_LISTING_URL'), 141 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 142 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 143 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL_PASSW', variable: 'TEST_USER_INBOX_PASSW'), 144 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 145 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 146 | // ]) { 147 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr3.txt"); 148 | // sh('npm run micro-bot-test'); 149 | // } 150 | // } 151 | // }, 152 | 153 | // "newegg-bot-test": { 154 | // image.inside(entryPoint) { 155 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_NEWEGG', variable: 'TEST_USER_LISTING_URL'), 156 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 157 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 158 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL_PASSW', variable: 'TEST_USER_INBOX_PASSW'), 159 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 160 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 161 | // ]) { 162 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr2.txt"); 163 | // sh('npm run newegg-bot-test'); 164 | // } 165 | // } 166 | // }, 167 | 168 | // "walmart-bot-test": { 169 | // image.inside(entryPoint) { 170 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_URL_WALMART', variable: 'TEST_USER_LISTING_URL'), 171 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 172 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 173 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL_PASSW', variable: 'TEST_USER_INBOX_PASSW'), 174 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 175 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV'), 176 | // ]) { 177 | // //echo("echo $TEST_USER_URL > $WORKSPACE/grr3.txt"); 178 | // sh('npm run walmart-bot-test'); 179 | // } 180 | // } 181 | // } 182 | ) 183 | 184 | //currentStage = 'all-bots-full-cycle test'; 185 | // stage(currentStage) { 186 | // image.inside(entryPoint) { 187 | // withCredentials([string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL', variable: 'TEST_USER_EMAIL'), 188 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_PASW', variable: 'TEST_USER_PASSW'), 189 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_EMAIL_PASSW', variable: 'TEST_USER_EMAIL_PASSW'), 190 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_LOC', variable: 'TEST_USER_LOC'), 191 | // string(credentialsId: 'PUPPET_PURCHASE_TEST_USER_CVV', variable: 'TEST_USER_CVV') 192 | // ]) { 193 | 194 | // } 195 | // } 196 | // } 197 | } 198 | catch (e) { 199 | currentBuild.result = 'FAILURE'; 200 | throw e 201 | } 202 | finally { 203 | stage('Create Archive'){ 204 | archiveArtifacts allowEmptyArchive: true, artifacts: '**', excludes: '**/node_modules/', followSymlinks: false; 205 | //archiveArtifacts allowEmptyArchive: true, artifacts: 'record/screen_shots/newegg/*.png, record/screen_shots/bestbuy/*.png, record/screen_shots/target/*.png'; 206 | } 207 | 208 | stage('cleanup'){ 209 | cleanWs(); 210 | sh('docker system prune -a -f'); 211 | } 212 | } 213 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Puppet-Purchase: Auto Purchase Scripts 2 | 3 | puppet-purchase is a bot that automates the process of purchasing an item from a few of the major online retailers. In attempt to combat scalping, I've created puppet-purchase bot and am making it publicly available with you all. Not perfect, but has helped me. Please share && contribute. 4 | 5 | These are scripts that automate the user flow of purchasing an item. 6 | That flow of purchasing an item varies a bit from website to website, but in general it is as follows: 7 | - Navigate to site 8 | - Sign-in to the account 9 | - Navigate to item listing page 10 | - If no is stock available: 11 | Switches store and refresh page until it finds available stock. 12 | - Adds item to cart 13 | - Checks-out cart 14 | 15 | 16 | ### Connecting it to your account 17 | 18 | To run these scripts, setting up an online account with one of the retailers is required. To ensure the scripts execute with no errors, be sure to plug in your account information. Each bot uses the **.env.userInfo** file located in _**scripts/< bot >/userInfo/.env.userInfo**_ to define user specific information. 19 | 20 | ### Note !!! 21 | ### _**Do not include your payment information.**_ 22 | All payment information should be setup by using your web browser, logging into the account, and adding a payment option. Not in the scripts. 23 | Avoid checking in personal account information to this repo / branches if you decide to contribute by adding _**env.userInfo**_ _**gitignore**_ 24 | Or even better, by creating a new a _**env.**_ file and pointing to it in _**scripts/< bot >/myInfo.js**_ 25 | 26 | ## Installation 27 | 28 | To run these script use [node.js](https://nodejs.org/en/) in order to install the required node modules. Navigate to the project directory and install npm. 29 | 30 | ```node 31 | npm i 32 | ``` 33 | Because of the way that the environment variables are defined, a version of [WSL](https://docs.microsoft.com/en-us/windows/wsl/) will need to be installed on your machine if running on windows machine. Alternatively, and perhaps an easier method for some, installing [Git](https://git-scm.com/downloads) and running the program using _**Git Bash**_ 34 | 35 | ## Usage 36 | Once npm finishes installing all the required node modules, the scripts are ready to go! Try filling out the necessary account info in _**scripts/< bot >/userInfo/.env.userInfo**_, then running one of the bots to see it in action. 37 | ```node 38 | npm run target-bot 39 | ``` 40 | A full list of available scripts can be found in _**package.json**_. We recommend running one of the bot-test to ensure everything is working properly. 41 | 42 | ## Test 43 | Running one of the bot-tests is the best way of making sure that the program is properly installed and running correctly. The bot-tests _**DO NOT**_ perform the last step - clicking the 'place order' button. Bot-tests are also a great way of making sure that your account has all the required information for a speedy checkout. 44 | 45 | When running the bot-tests, test-user information will need to be added as environment variables instead of being added to _**env.userInfo**_ file. This is the list of all test-user variable 46 | 47 | ```node 48 | export TEST_USER_EMAIL= \ 49 | TEST_USER_PASSW= \ 50 | TEST_USER_INBOX_PASSW= \ 51 | TEST_USER_PHONE= \ 52 | TEST_USER_LOC= \ 53 | TEST_USER_CVV= \ 54 | TEST_USER_LISTING_URL= \ 55 | ``` 56 | Use 'export' if you're on Linux or 'SET' if you're on Windows. 57 | 58 | Some environment variables are not required for all of the bot-test, such as TEST_USER_INBOX_PASSW && TEST_USER_LOC. Look inside the _**env.userInfo**_ file that pertains to the specific bot inorder to know what variables the program is expecting. 59 | 60 | We find it easier to export all of the variables, and just change the TEST_USER_LISTING_URL variable depending on what bot-tests is we expect to run. 61 | 62 | 63 | ## Docker 64 | Alternatively, you can run the program inside a docker container. Use the _**Dockerfile**_ provided to make a docker image and then run it inside a docker container. 65 | ```node 66 | docker build -t puppet-purchase . 67 | docker run -p 5901:5901 -d puppet-purchase 68 | ``` 69 | 70 | ## VNC 71 | Use [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to look inside the container and view the process. By default it is running on port 5901. Feel free to change the default port by editing the -p flag and the _**Dockerfile**_ 72 | ```node 73 | # Inside Dockerfile, add this 74 | EXPOSE [new_port_number] 75 | ``` 76 | default password: puppeteer 77 | 78 | ## Contributing 79 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 80 | 81 | Please make sure to update tests as appropriate. 82 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | // Write PRIORITY 2 | #PRIORITY: FIX JENKINS PIPELINE 3 | #PRIORITY: MAKE SERVER MORE SECURE!!! 4 | 5 | // Write FIXME 6 | #FIXME: Fix gamestop bot.. 7 | #FIXME: test user keeps gets shadow-banned for a period.. 8 | - Need to think of solution so that it doesnt slow down dev time 9 | 10 | // Write TODO 11 | #TODO: Improve speed efficiency of scripts 12 | -After it arrives to item listing page 13 | #TODO: Run manually in jenkins 14 | #TODO: Make sure it runs in the server 15 | #TODO: Upgrade to latest jenkins. 16 | #TODO: Set up ssh keys? 17 | #TODO: Setup vpn 18 | #TODO: Remove ability to create terminal in jenkins 19 | 20 | 21 | // Write COMPLETE 22 | #COMPLETE TODO: Fix taget screenShotPath error 23 | #COMPLETE TODO: Create selector variable file for bestbuy-bot 24 | #COMPLETE TODO: Create .env files for each bot 25 | + Target 26 | + BestBuy 27 | + Newegg 28 | #COMPLETE FIXME: Change varible to use env.vars to work with docker. 29 | #COMPLETE PRIORITY: Create test user 30 | + Bestbuy 31 | + Target 32 | + Newegg 33 | #COMPLETE FIXME: findlisting 'Error: No node found for selector: .zip-code-input' 34 | #COMPLETE TODO: Integrate with Jenkins pipeline 35 | #COMPLETE target bot selector names changed 36 | #COMPLETE Integrate utils.js with myinfo.js 37 | #COMPLETE Create run-all-bots scipt command in package.json 38 | #COMPLETE Add step in all bots to skip last step (purchase button) if running in testing environment 39 | #COMPLETE TODO: Create a MicroCenter bot !!! 40 | #COMPLETE TODO: Create a Walmart bot !!! 41 | #COMPLETE TODO: Update readme.md to include instructions for docker and setting up user information 42 | #COMPLETE FIXME: target screenshots ending up in root folder 43 | #COMPLETE FIXME: edit readme to explain how to properly use newegg-bot 44 | - No longer needs manual steps! 45 | #COMPLETE TODO:Updated jenkins server to latest version, 46 | -Had some issues with roleStrategyPlugin that would cause jenkins to exit on startup, had to remove all from the config.xml and set useSecurity to false, so that jenkinswould auto generate it. Never pasted back the , but somehow jenkins remembers the users, not sure about the user permissions. 47 | -Had to tickoff an option in security configuration to enable security again. 48 | #COMPLETE TODO: Convert to run in headless!! 49 | - Took all night to pull off, but I was able to get through all the errors that came up due to running in headless mode. 50 | - Currently testing is halted.. Not sure if I can run this program in headless mode. I think all of these sites are using some sort of bot detection. Tried it with two different account and they both fail at the login attempt. 51 | 52 | #REJECTED TODO: Create Amazon bot 53 | - Not sure how I'd make it to only buy items sold exclusively by amazon. 54 | - -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-purchase", 3 | "version": "0.3.0", 4 | "description": "puppet-purchase", 5 | "author": "Yelsin S", 6 | "private": true, 7 | "scripts": { 8 | "all-bots-find-stock": "sh scripts/test/all-bots-find-stocks.test.sh", 9 | "all-bots-full-cycle": "sh scripts/test/all-bots-full-cycle.test.sh", 10 | "bestbuy-bot": "sh scripts/bestbuy/build.sh", 11 | "gamestop-bot": "sh scripts/gamestop/build.sh", 12 | "micro-bot": "sh scripts/microcenter/build.sh", 13 | "newegg-bot": "sh scripts/newegg/build.sh", 14 | "target-bot": "sh scripts/target/build.sh", 15 | "walmart-bot": "sh scripts/walmart/build.sh", 16 | "bestbuy-bot-test": "sh scripts/test/bestbuy-bot.test.sh", 17 | "gamestop-bot-test": "sh scripts/test/gamestop-bot.test.sh", 18 | "micro-bot-test": "sh scripts/test/micro-bot.test.sh", 19 | "newegg-bot-test": "sh scripts/test/newegg-bot.test.sh", 20 | "target-bot-test": "sh scripts/test/target-bot.test.sh", 21 | "walmart-bot-test": "sh scripts/test/walmart-bot.test.sh", 22 | "bestbuy-find-stocks-test": "sh scripts/test/bestbuy-find-stocks.test.sh", 23 | "gamestop-find-stocks-test": "sh scripts/test/gamestop-find-stocks.test.sh", 24 | "micro-find-stocks-test": "sh scripts/test/micro-find-stocks.test.sh", 25 | "newegg-find-stocks-test": "sh scripts/test/newegg-find-stocks.test.sh", 26 | "target-find-stocks-test": "sh scripts/test/target-find-stocks.test.sh", 27 | "walmart-find-stocks-test": "sh scripts/test/walmart-find-stocks.test.sh" 28 | }, 29 | "dependencies": { 30 | "balanced-match": "^1.0.0", 31 | "cli-spinner": "^0.2.10", 32 | "colors": "1.4.0", 33 | "core-util-is": "^1.0.2", 34 | "dotenv": "8.2.0", 35 | "puppeteer": "^8.0.0", 36 | "webpack-dev-server": "^3.11.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /puppeteer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/puppeteer.ico -------------------------------------------------------------------------------- /record/screen_shots/bestbuy/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/record/screen_shots/bestbuy/sample.png -------------------------------------------------------------------------------- /record/screen_shots/gamestop/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/record/screen_shots/gamestop/sample.png -------------------------------------------------------------------------------- /record/screen_shots/microcenter/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/record/screen_shots/microcenter/sample.png -------------------------------------------------------------------------------- /record/screen_shots/newegg/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/record/screen_shots/newegg/sample.png -------------------------------------------------------------------------------- /record/screen_shots/target/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/record/screen_shots/target/sample.png -------------------------------------------------------------------------------- /record/screen_shots/walmart/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yorisoft/puppet-purchase/7fabfddc10d05f848a95e10a1b6701fdfe5ab5bb/record/screen_shots/walmart/sample.png -------------------------------------------------------------------------------- /scripts/bestbuy/bestbuy-bot.js: -------------------------------------------------------------------------------- 1 | const utils = require("./utils"); 2 | const myInfo = require("./myInfo"); 3 | const taskHandler = require("./taskHandler"); 4 | const Spinner = require("cli-spinner"); 5 | const puppeteer = require("puppeteer"); 6 | const colors = require("colors"); 7 | 8 | 9 | async function addToCart(page) { 10 | try { 11 | await page.waitForSelector(utils.selectors.get("add_cart_bttn_selector")); 12 | await page.waitForTimeout(2000); 13 | await page.focus(utils.selectors.get("add_cart_bttn_selector")); 14 | await page.keyboard.press("Enter"); 15 | console.log("Item added to cart .."); 16 | 17 | await page.waitForTimeout(1000); 18 | await page.screenshot({ path: `${myInfo.snapShotPath}+added_to_cart.png` }); 19 | } catch (err) { 20 | console.log("\n" + err); 21 | throw err; 22 | } 23 | } 24 | 25 | async function bestbuyBot() { 26 | // Spinner 27 | var mySpinner = new Spinner.Spinner("processing.. %s"); 28 | mySpinner.setSpinnerString("|/-\\"); 29 | mySpinner.start(); 30 | 31 | try { 32 | let launcherArgs; 33 | let pathToBrowser= process.env.PUPPETEER_EXEC_PATH; 34 | if (process.env.USER_ENV === 'testUserInfo') { 35 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', '--disable-setuid-sandbox', `--window-size=1025,1025`]; 36 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 37 | } else { 38 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 39 | } 40 | 41 | // Start of test: Launch and go to login website 42 | const browser = await puppeteer.launch({ 43 | defaultViewport: null, 44 | headless: false, // not sure about running headless.. Bot detection. 45 | args: launcherArgs, 46 | executablePath: pathToBrowser, 47 | }); 48 | 49 | const page = await browser.newPage(); 50 | await page.setDefaultNavigationTimeout(0); 51 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 52 | await page.goto("https://www.bestbuy.com", { waitUntil: "networkidle2" }); 53 | await taskHandler.logIn(page); 54 | 55 | // TESTING - Comment out when done. 56 | // For cleaning up account/pause program - usefull for test setup 57 | // await page.waitForTimeout(9000000); 58 | 59 | // Navigate to Sony PS5 listing & add to cart 60 | let amountOrdered = 0; 61 | while (amountOrdered < 1) { 62 | 63 | console.log("\n[1/4] .. Navigating to listing page ..".bgBlue); 64 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 65 | await page.goto(`${myInfo.listingURL}`); 66 | console.log(`${myInfo.listingURL}`); 67 | await page.screenshot({ 68 | path: `${myInfo.snapShotPath}+listing_page.png`, 69 | }); 70 | 71 | // Checking to see if listing is out of stock 72 | await page.waitForSelector(utils.selectors.get("pickUp_bttn_selector")); 73 | let stocks = await page.$eval( 74 | utils.selectors.get("pickUp_bttn_selector"), 75 | (element) => { 76 | return element.innerHTML; 77 | } 78 | ); 79 | let isInStock = stocks.includes("Add"); 80 | let testRuns = 0; 81 | while (!isInStock) { 82 | console.log("\nProduct is OUT OF STOCK".red); 83 | 84 | const npage = await browser.newPage(); 85 | await npage.goto("https://www.bestbuy.com/site/store-locator/"); 86 | await page.waitForTimeout(500); 87 | await npage.screenshot({ 88 | path: `${myInfo.snapShotPath}+store_locator.png`, 89 | }); 90 | 91 | isInStock = await taskHandler.findListing(page, npage); 92 | await npage.close(); 93 | 94 | //EXIT IF RUNNING TEST 95 | if ((`${process.env.USER_ENV}` == "testUserInfo" && testRuns == 1)) { 96 | return; 97 | } 98 | testRuns++; 99 | } 100 | console.log("\nListing is in stock !!".bgBlue); 101 | 102 | // Add listing to cart 103 | console.log("\n[2/4] .. Adding item to cart ..".bgBlue); 104 | await addToCart(page); 105 | 106 | // Navigate to cart 107 | console.log("\n[3/4] .. Navigating to cart ..".bgBlue); 108 | const cartURL = "https://www.bestbuy.com/cart"; 109 | await page.goto(`${cartURL}`); 110 | await page.waitForTimeout(500); 111 | await page.screenshot({ path: `${myInfo.snapShotPath}+nav_to_cart.png` }); 112 | 113 | //Checkout listing 114 | console.log("\n[4/4] .. Checking out cart ..".bgBlue); 115 | await taskHandler.checkoutCart(page); 116 | 117 | // Ctrl+C && Celebrate 118 | console.log("\nDone. Goteee boiiis!!! \n".rainbow); 119 | console.log("\nLook at account purchase history to verify \n".bgRed); 120 | 121 | // Done 122 | await page.goto( 123 | "https://www.tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254", 124 | { waitUntil: "networkidle2" } 125 | ); 126 | amountOrdered++; 127 | } 128 | await page.waitForTimeout(7000); 129 | await page.close(); 130 | await browser.close(); 131 | await mySpinner.stop(); 132 | } 133 | catch (err) { 134 | // expected output: ReferenceError: nonExistentFunction is not defined 135 | // Note - error messages will vary depending on browser 136 | 137 | console.log('\n' + err); 138 | throw err; 139 | } 140 | finally { 141 | 142 | return; 143 | } 144 | 145 | } 146 | 147 | bestbuyBot(); 148 | -------------------------------------------------------------------------------- /scripts/bestbuy/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$USER_ENV" ] 4 | then 5 | export USER_ENV=userInfo 6 | else 7 | export USER_ENV=$USER_ENV 8 | fi 9 | echo "Environmnet: $USER_ENV\_environment" 10 | 11 | USER_ENV=$USER_ENV node scripts/bestbuy/bestbuy-bot.js 12 | 13 | exit -------------------------------------------------------------------------------- /scripts/bestbuy/myInfo.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: `scripts/bestbuy/user_info/.env.${process.env.USER_ENV}` }); 2 | var date = new Date(); 3 | var timeStamp = `${process.env.USER_ENV}_${date.getMonth()}-${date.getDay()}_${Math.floor(Math.random() * 100001)}`; 4 | let snapShotPath = 'record/screen_shots/bestbuy/' + `${timeStamp}`; 5 | 6 | let myemail; 7 | let mypassw; 8 | let myloc; 9 | let mycvv; 10 | let listingURL; 11 | 12 | if (`${process.env.USER_ENV}` === 'testUserInfo') { 13 | myemail = process.env.TEST_USER_EMAIL; 14 | mypassw = process.env.TEST_USER_PASSW; 15 | myloc = process.env.TEST_USER_LOC; 16 | mycvv = process.env.TEST_USER_CVV; 17 | listingURL = process.env.TEST_USER_LISTING_URL; 18 | } else { 19 | myemail = process.env.MY_EMAIL; 20 | mypassw = process.env.MY_PASSW; 21 | myloc = process.env.MY_LOC; 22 | mycvv = process.env.MY_CVV; 23 | listingURL = process.env.LISTING_URL; 24 | } 25 | 26 | module.exports = { 27 | myemail, 28 | mypassw, 29 | myloc, 30 | mycvv, 31 | listingURL, 32 | snapShotPath, 33 | }; -------------------------------------------------------------------------------- /scripts/bestbuy/taskHandler.js: -------------------------------------------------------------------------------- 1 | const myInfo = require('./myInfo'); 2 | const utils = require('./utils'); 3 | const colors = require('colors'); 4 | 5 | async function logIn(page) { 6 | try { 7 | // LOGIN 8 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 9 | await page.waitForSelector(utils.selectors.get('account_selector')); 10 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 11 | 12 | let list_items = await page.$eval( 13 | utils.selectors.get('account_selector'), 14 | (element) => { 15 | return element.innerText; 16 | } 17 | ); 18 | let needsLogIn = list_items.includes('Account'); 19 | 20 | // Navigate to login page 21 | while (needsLogIn) { 22 | console.log('Navigating to signin page ..'.yellow); 23 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 24 | await page.goto('https://www.bestbuy.com/signin'); 25 | await page.waitForTimeout(700); // Avoid network slowdown 26 | 27 | // Enter login credentials & signin 28 | console.log('Signing in ..'.yellow); 29 | 30 | //email 31 | await page.waitForSelector(utils.selectors.get('email_selector')); 32 | await page.$eval(utils.selectors.get('email_selector'), (el) => el.click()); 33 | await page.type(utils.selectors.get('email_selector'), `${myInfo.myemail}`, {delay: 150}); 34 | 35 | //password 36 | await page.$eval(utils.selectors.get('password_selector'), (el) => 37 | el.click() 38 | ); 39 | await page.type(utils.selectors.get('password_selector'), `${myInfo.mypassw}`, {delay: 150}); 40 | 41 | //submit 42 | await page.focus(utils.selectors.get('singin_selector')); 43 | await page.keyboard.press('Enter'); 44 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_attempt.png` }); 45 | 46 | await page.waitForTimeout(4000); // Time to load account username 47 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_attempt.png` }); 48 | await page.waitForSelector(utils.selectors.get('account_selector')); 49 | list_items = await page.$eval( 50 | utils.selectors.get('account_selector'), 51 | (element) => { 52 | return element.innerText; 53 | } 54 | ); 55 | needsLogIn = list_items.includes('Account'); 56 | } 57 | console.log('Signed in succesfully ..'.yellow); 58 | } catch (err) { 59 | console.log("\n" + err); 60 | throw err; 61 | } 62 | } 63 | 64 | async function findListing(page, npage) { 65 | await npage.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 66 | 67 | let stocks; 68 | let isInStock; 69 | let n = 1; 70 | 71 | try{ 72 | await npage.waitForSelector(utils.selectors.get('zip_input_selector')); 73 | await npage.waitForSelector(utils.selectors.get('lookup_bttn_selector')); 74 | 75 | console.log('starting forloop'); 76 | for (let i = 0; i < 5; i++) { 77 | await npage.$eval(utils.selectors.get('zip_input_selector'), (el) => 78 | el.click() 79 | ); 80 | await npage.type(utils.selectors.get('zip_input_selector'), myInfo.myloc); 81 | await npage.$eval(utils.selectors.get('lookup_bttn_selector'), (el) => 82 | el.click() 83 | ); 84 | await npage.waitForTimeout(300); 85 | await npage.screenshot({ path: `${myInfo.snapShotPath}+find_store2.png` }); 86 | 87 | await npage.waitForSelector(utils.selectors.get('pick_store_selector')); 88 | let bttns = await npage.$$(utils.selectors.get('pick_store_selector')); 89 | await bttns[i].click(); 90 | await npage.waitForTimeout(500); 91 | await npage.screenshot({ 92 | path: `${myInfo.snapShotPath}_change_store_${n++}.png`, 93 | }); 94 | console.log('\nSwitched Stores'.yellow); 95 | 96 | // Check if current store has listing 97 | await page.bringToFront(); 98 | await page.reload(); 99 | await page.waitForSelector(utils.selectors.get('pickUp_bttn_selector')); 100 | 101 | stocks = await page.$eval( 102 | utils.selectors.get('pickUp_bttn_selector'), 103 | (element) => { 104 | return element.innerHTML; 105 | } 106 | ); 107 | isInStock = stocks.includes('Add'); 108 | console.log('isInStock: ' + `${isInStock}`.red); 109 | 110 | let currentStore = await npage.$$('div.shop-location-card'); 111 | let itemJsHandle = await currentStore[i + 1].getProperty('innerText'); 112 | let storeText = await itemJsHandle.jsonValue(); 113 | console.log('@ : ' + `${storeText}`.red); 114 | 115 | // Stop switching stores if listing is found 116 | if (isInStock = true) { 117 | break; 118 | } 119 | } 120 | return isInStock; 121 | } catch(err){ 122 | console.log("\n" + err); 123 | throw err; 124 | } 125 | } 126 | 127 | async function checkoutCart(page) { 128 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 129 | 130 | try{ 131 | await page.waitForSelector(utils.selectors.get('chekout_bttn_selector_1')); 132 | await page.focus(utils.selectors.get('chekout_bttn_selector_1')); 133 | await page.keyboard.press('Enter'); 134 | 135 | await page.waitForTimeout(300); 136 | await page.screenshot({ 137 | path: `${myInfo.snapShotPath}+checkout_started.png`, 138 | }); 139 | 140 | page.evaluate(_ => { 141 | window.scrollBy(10, window.innerHeight); 142 | }); 143 | 144 | // If proceed button is present, then click on it 145 | await page.waitForTimeout(1000); 146 | await page.waitForSelector('#checkoutApp > div.page-spinner.page-spinner--out > div:nth-child(1) > div.checkout.large-view.fast-track > main > div.checkout__container.checkout__container-fast-track > div.checkout__col.checkout__col--secondary.fast-track--align-top.anchor > section.order-summary.order-summary--inactive.order-summary__fast-track > div.order-summary__bd--fast-track > section > div > div.order-summary__total > div.order-summary__price > span'); 147 | if (await page.$(utils.selectors.get('proceed_to_checkout')) !== null){ 148 | await page.focus(utils.selectors.get('proceed_to_checkout')); 149 | await page.keyboard.press('Enter'); 150 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_proceed.png` }); 151 | } 152 | 153 | // Input credit-card cvv 154 | await page.waitForSelector(utils.selectors.get('chekout_bttn_selector_2')); 155 | if (await page.$(utils.selectors.get('cvv_bttn_selector')) !== null){ 156 | await page.focus(utils.selectors.get('cvv_bttn_selector')); 157 | await page.keyboard.press('Enter'); 158 | await page.type(utils.selectors.get('cvv_bttn_selector'), `${myInfo.mycvv}`); 159 | await page.screenshot({ path: `${myInfo.snapShotPath}+cvv_added.png` }); 160 | } 161 | 162 | //Moment of truth.. 163 | await page.focus(utils.selectors.get('chekout_bttn_selector_2')); 164 | //SKIP IF RUNNING TEST 165 | if (`${process.env.USER_ENV}` == "userInfo" ) { 166 | await page.keyboard.press('Enter'); 167 | } 168 | await page.waitForTimeout(7000); 169 | await page.screenshot({ path: `${myInfo.snapShotPath}+result_page.png` }); 170 | } catch(err){ 171 | console.log("\n" + err); 172 | throw err; 173 | } 174 | } 175 | 176 | module.exports = { 177 | logIn, 178 | findListing, 179 | checkoutCart, 180 | }; 181 | -------------------------------------------------------------------------------- /scripts/bestbuy/user_info/.env.userInfo: -------------------------------------------------------------------------------- 1 | #enter email 2 | MY_EMAIL= 3 | 4 | #enter password 5 | MY_PASSW= 6 | 7 | #enter zip code 8 | MY_LOC= 9 | 10 | #enter payment card cvv 11 | MY_CVV= 12 | 13 | #enter listing url 14 | LISTING_URL= -------------------------------------------------------------------------------- /scripts/bestbuy/utils.js: -------------------------------------------------------------------------------- 1 | let selectors = new Map(); 2 | selectors.set('pickUp_bttn_selector', 'div.fulfillment-add-to-cart-button'); 3 | selectors.set('add_cart_bttn_selector', 'button.c-button.c-button-primary.c-button-lg.c-button-block.c-button-icon.c-button-icon-leading.add-to-cart-button'); 4 | selectors.set('account_selector', 'li.bottom-nav-menu-item'); 5 | selectors.set('zip_input_selector', '.zip-code-input'); 6 | selectors.set('pick_store_selector', 'button.c-button.c-button-outline.c-button-sm.make-this-your-store'); 7 | selectors.set('lookup_bttn_selector', 'button.c-button.c-button-secondary.c-button-md'); 8 | selectors.set('email_selector', 'input#fld-e.tb-input'); 9 | selectors.set('password_selector', 'input#fld-p1.tb-input'); 10 | selectors.set('singin_selector', 'div.cia-form__controls'); 11 | selectors.set('chekout_bttn_selector_1', 'button.btn.btn-lg.btn-block.btn-primary'); 12 | selectors.set('chekout_bttn_selector_2', 'button.btn.btn-lg.btn-block.btn-primary.button__fast-track'); 13 | selectors.set('proceed_to_checkout', '#checkoutApp > div.page-spinner.page-spinner--out > div:nth-child(1) > div.checkout.large-view > main > div.checkout__container > div.checkout__col.checkout__col--primary > form > section > div > div:nth-child(2) > div > div > button'); 14 | selectors.set('cvv_panel_selector', 'div.checkout-panel payment-card'); 15 | selectors.set('cvv_bttn_selector', 'input#credit-card-cvv.form-control.credit-card-form__cvv--warn'); 16 | 17 | module.exports = { 18 | selectors, 19 | } -------------------------------------------------------------------------------- /scripts/gamestop/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$USER_ENV" ] 4 | then 5 | export USER_ENV=userInfo 6 | else 7 | export USER_ENV=$USER_ENV 8 | fi 9 | echo "Environmnet: $USER_ENV\_environment" 10 | 11 | USER_ENV=$USER_ENV node scripts/gamestop/gamestop-bot.js -------------------------------------------------------------------------------- /scripts/gamestop/gamestop-bot.js: -------------------------------------------------------------------------------- 1 | const taskHandler = require('./taskHandler'); 2 | const myInfo = require('./myInfo'); 3 | const utils = require('./utils'); 4 | const Spinner = require('cli-spinner'); 5 | const puppeteer = require('puppeteer'); 6 | const colors = require('colors'); 7 | 8 | async function addToCart(page) { 9 | await page.waitForSelector(utils.selectors.get("cart_inventory_selector")); 10 | let oldItemCount = await page.$eval(utils.selectors.get('cart_inventory_selector'), 11 | (element) => { return element.innerText }); 12 | 13 | // It takes a reload and 6 keyboard presses to get the item to be added to cart for some reason 14 | while (!oldItemCount.includes('1')) { 15 | console.log(oldItemCount); 16 | await page.waitForSelector(utils.selectors.get("pickUp_bttn_selector")); 17 | await page.$eval(utils.selectors.get("pickUp_bttn_selector"), (el) => 18 | el.click({ clickCount: 2 })); 19 | //await page.focus(utils.selectors.get("pickUp_bttn_selector")); 20 | //await page.keyboard.press('Enter'); 21 | await page.waitForTimeout(3000); 22 | 23 | await page.waitForSelector(utils.selectors.get("cart_inventory_selector")); 24 | oldItemCount = await page.$eval(utils.selectors.get('cart_inventory_selector'), (element) => { return element.innerText }); 25 | //await page.reload(); 26 | } 27 | 28 | console.log('Item added to cart ..'); 29 | await page.screenshot({ path: `${myInfo.snapShotPath}+added_to_cart.png` }); 30 | 31 | } 32 | 33 | async function gamestopBot() { 34 | // Spinner 35 | var mySpinner = new Spinner.Spinner('processing.. %s'); 36 | mySpinner.setSpinnerString('|/-\\'); 37 | mySpinner.start(); 38 | 39 | try { 40 | 41 | let launcherArgs; 42 | let pathToBrowser; 43 | if (process.env.USER_ENV === 'testUserInfo') { 44 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', '--disable-setuid-sandbox', `--window-size=1025,1025`]; 45 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 46 | } else { 47 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 48 | } 49 | 50 | // Start of test: Launch and go to login website 51 | const browser = await puppeteer.launch({ 52 | defaultViewport: null, 53 | headless: false, // not sure about running headless.. Bot detection. 54 | args: launcherArgs, 55 | executablePath: pathToBrowser, 56 | }); 57 | 58 | const page = await browser.newPage(); 59 | await page.setDefaultNavigationTimeout(0); 60 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 61 | await page.goto('https://www.gamestop.com/', { waitUntil: 'networkidle2' }); 62 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 63 | 64 | // TESTING - Comment out when done. 65 | // await cleanUpAccount(page); 66 | // For cleaning up account/pause program - usefull for test setup 67 | // await page.waitForTimeout(9000000); 68 | 69 | // Navigate to listing & add to cart 70 | let amountOrdered = 0; 71 | while (amountOrdered < 1) { 72 | 73 | console.log('\n[1/4] .. Navigating to listing page ..'.bgBlue); 74 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 75 | await page.goto(`${myInfo.listingURL}`, { waitUntil: 'networkidle2' }); 76 | console.log(`${myInfo.listingURL}`); 77 | await page.screenshot({ path: `${myInfo.snapShotPath}+listing_page.png` }); 78 | 79 | // Checking to see if listing is out of stock 80 | let stocks = await page.$eval(utils.selectors.get('pickUp_bttn_selector'), (element) => { return element.innerHTML }); 81 | let isOutOfStock = stocks.includes('Not Available'); 82 | console.log('isOutOfStock: ' + `${isOutOfStock}`.red); 83 | 84 | // While listing is out of stock: Change store, check availability 85 | let testRuns = 0; 86 | while (isOutOfStock) { 87 | console.log('\nProduct is OUT OF STOCK'.red); 88 | 89 | const npage = await browser.newPage(); 90 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 91 | await npage.goto("https://www.gamestop.com/stores/", { waitUntil: 'networkidle2' }); 92 | await npage.screenshot({ path: `${myInfo.snapShotPath}+store_locator.png` }); 93 | 94 | isOutOfStock = await taskHandler.findListing(npage); 95 | await npage.close(); 96 | 97 | if ((`${process.env.USER_ENV}` == 'testUserInfo' && testRuns == 1)) { 98 | return; 99 | } 100 | testRuns++; 101 | } 102 | console.log('\nListing is in stock !!'.bgBlue); 103 | 104 | // Add listing to cart 105 | console.log('\n[2/4] .. Adding item to cart ..'.bgBlue); 106 | await page.waitForTimeout(500); 107 | await addToCart(page); 108 | 109 | // Navigate to cart 110 | console.log('\n[3/4] .. Navigating to cart ..'.bgBlue); 111 | const cartURL = 'https://www.gamestop.com/cart/'; 112 | await page.goto(`${cartURL}`, { waitUntil: 'networkidle2' }); 113 | await page.screenshot({ path: `${myInfo.snapShotPath}+nav_to_cart.png` }); 114 | 115 | //Checkout listing 116 | console.log('\n[4/4] .. Checking out cart ..'.bgBlue); 117 | await taskHandler.checkoutCart(page); 118 | 119 | // Ctrl+C && Celebrate 120 | console.log('\nDone. Goteee boiiis!!! \n'.rainbow); 121 | console.log('\nCtrl+C && Celebrate \n'.bgRed); 122 | 123 | // Done 124 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 125 | await page.goto('https://www.tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254', { waitUntil: 'networkidle2' }); 126 | amountOrdered++; 127 | } 128 | await page.waitForTimeout(7000); 129 | await page.close(); 130 | await browser.close(); 131 | await mySpinner.stop(); 132 | await process.exit(); 133 | return; 134 | } catch (error) { 135 | console.log('\n' + error); 136 | } finally { 137 | 138 | } 139 | } 140 | 141 | gamestopBot(); -------------------------------------------------------------------------------- /scripts/gamestop/myInfo.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: `scripts/gamestop/user_info/.env.${process.env.USER_ENV}`}); 2 | var date = new Date(); 3 | var timeStamp = `${process.env.USER_ENV}_${date.getMonth()}-${date.getDay()}_${Math.floor(Math.random() * 100001)}`; 4 | let snapShotPath = 'record/screen_shots/gamestop/' + `${timeStamp}`; 5 | 6 | let myemail; 7 | let mypassw; 8 | let myloc; 9 | let mycvv; 10 | let listingURL; 11 | 12 | if (`${process.env.USER_ENV}` === 'testUserInfo') { 13 | myemail = process.env.TEST_USER_EMAIL; 14 | mypassw = process.env.TEST_USER_PASSW; 15 | myloc = process.env.TEST_USER_LOC; 16 | mycvv = process.env.TEST_USER_CVV; 17 | listingURL = process.env.TEST_USER_LISTING_URL; 18 | } else { 19 | myemail = process.env.MY_EMAIL; 20 | mypassw = process.env.MY_PASSW; 21 | myloc = process.env.MY_LOC; 22 | mycvv = process.env.MY_CVV; 23 | listingURL = process.env.LISTING_URL; 24 | } 25 | 26 | module.exports = { 27 | myemail, 28 | mypassw, 29 | myloc, 30 | mycvv, 31 | listingURL, 32 | snapShotPath, 33 | }; -------------------------------------------------------------------------------- /scripts/gamestop/taskHandler.js: -------------------------------------------------------------------------------- 1 | const Spinner = require("cli-spinner"); 2 | const colors = require("colors"); 3 | const myInfo = require("./myInfo"); 4 | const utils = require("./utils"); 5 | 6 | async function logIn(page) { 7 | await page.waitForTimeout(1000); 8 | // Navigate to login page 9 | let signingText; 10 | let isSignedout; 11 | 12 | //signingText = await page.$eval("singin_selector_1", (el) => {return el.innerText}); 13 | //isSignedout = signingText.includes("MY ACCOUNT"); 14 | //console.log("signingText: " + signingText); 15 | //console.log("isSignedout: " + isSignedout); 16 | 17 | //while (isSignedout) { 18 | /* await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 19 | await page.goto('https://www.gamestop.com/checkout/login/', { waitUntil: 'networkidle2' }); 20 | console.log('Navigating to signin ..'.yellow); */ 21 | 22 | /* await page.$eval(utils.selectors.get("singin_selector_1"), (el) => 23 | el.click() 24 | ); 25 | await page.$eval(utils.selectors.get("singin_selector_2"), (el) => 26 | el.click() 27 | ); */ 28 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_page.png` }); 29 | 30 | // Enter login credentials & signin 31 | //email 32 | console.log("Signing in ..".yellow); 33 | await page.$eval(utils.selectors.get("email_selector"), (el) => el.click()); 34 | await page.type(utils.selectors.get("email_selector"), myInfo.myemail); 35 | 36 | //password 37 | await page.$eval(utils.selectors.get("password_selector"), (el) =>el.click()); 38 | await page.type(utils.selectors.get("password_selector"), myInfo.mypassw); 39 | 40 | //submit 41 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_submit.png` }); 42 | await page.$eval(utils.selectors.get("singin_selector_3"), (el) =>el.click()); 43 | 44 | /* await page.waitForSelector(utils.selectors.get("singin_selector_1")); 45 | await page.waitForTimeout(400); // Allow text to load 46 | signingText = await page.$eval(utils.selectors.get("singin_selector_1"), 47 | (el) => {return el.innerText}); 48 | isSignedout = signingText.includes("MY ACCOUNT"); 49 | 50 | console.log("signingText: " + signingText); 51 | console.log("isSignedout: " + isSignedout); */ 52 | //} 53 | 54 | await page.waitForTimeout(1000); 55 | console.log("Signed in succesfully ..".yellow); 56 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_success.png` }); 57 | } 58 | 59 | async function findListing(page) { 60 | let stocks; 61 | let isOutOfStock; 62 | 63 | for (let i = 0; i < 5; i++) { 64 | /* await page.$eval(utils.selectors.get("change_store_selector"), (el) =>el.click()); 65 | await page.waitForTimeout(500); 66 | await page.screenshot({ path: `${myInfo.snapShotPath}+find_store1.png` }); */ 67 | 68 | await page.$eval(utils.selectors.get("zip_input_selector"), (el) => el.click()); 69 | await page.type(utils.selectors.get("zip_input_selector"), myInfo.myloc); 70 | await page.$eval(utils.selectors.get("lookup_bttn_selector"), (el) => el.click()); 71 | await page.waitForTimeout(500); 72 | await page.screenshot({ path: `${myInfo.snapShotPath}+find_store2.png` }); 73 | 74 | let bttns = await page.$$(utils.selectors.get("pick_store_selector")); 75 | await bttns[i].click(); 76 | await page.waitForTimeout(500); 77 | await page.screenshot({path: `${myInfo.snapShotPath}_change_store_${i}.png`}); 78 | console.log("\nSwitched Stores".yellow); 79 | 80 | // Check if current store has listing 81 | stocks = await page.$eval(utils.selectors.get("pickUp_bttn_selector"), 82 | (element) => { 83 | return element.innerHTML; 84 | } 85 | ); 86 | isOutOfStock = stocks.includes('Not Available'); 87 | console.log("isOutOfStock: " + `${isOutOfStock}`.red); 88 | 89 | // Stop switching stores if listing is found 90 | if (isOutOfStock != true) { 91 | break; 92 | } 93 | } 94 | return isOutOfStock; 95 | } 96 | 97 | async function checkoutCart(page) { 98 | await page.$eval(utils.selectors.get("chekout_bttn_selector_1"), (el) => 99 | el.click() 100 | ); 101 | await page.waitForTimeout(500); 102 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_process1.png` }); 103 | 104 | // Signing in 105 | await logIn(page); 106 | 107 | await page.waitForSelector(utils.selectors.get("chekout_bttn_selector_2")); 108 | await page.$eval(utils.selectors.get("chekout_bttn_selector_2"), (el) => el.click()); 109 | await page.waitForTimeout(500); 110 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_process2.png` }); 111 | 112 | await page.waitForSelector(utils.selectors.get("chekout_bttn_selector_3")); 113 | if ((await page.$(utils.selectors.get("cvv_bttn_selector"))) !== null) { 114 | await page.waitForTimeout(500); 115 | await page.$eval(utils.selectors.get("cvv_bttn_selector"), (el) => 116 | el.click() 117 | ); 118 | await page.type(utils.selectors.get("cvv_bttn_selector"), myInfo.mycvv); 119 | await page.screenshot({ path: `${myInfo.snapShotPath}+cvv_added.png` }); 120 | await page.$eval(utils.selectors.get("chekout_bttn_selector_3"), (el) => el.click()); 121 | } 122 | 123 | // Checkout = 'Moment of truth..'; 124 | await page.waitForSelector(utils.selectors.get("place_order_selector")); 125 | await page.focus(utils.selectors.get("place_order_selector")); 126 | //SKIP IF RUNNING TEST 127 | if (`${process.env.USER_ENV}` == "userInfo" ) { 128 | await page.keyboard.press('Enter'); 129 | } 130 | await page.waitForTimeout(7000); 131 | await page.screenshot({ path: `${myInfo.snapShotPath}+result_page.png` }); 132 | } 133 | 134 | module.exports = { 135 | logIn, 136 | findListing, 137 | checkoutCart, 138 | }; 139 | -------------------------------------------------------------------------------- /scripts/gamestop/user_info/.env.userInfo: -------------------------------------------------------------------------------- 1 | #Enter email 2 | MY_EMAIL= 3 | 4 | #Enter password 5 | MY_PASSW= 6 | 7 | #Enter zip code 8 | MY_LOC= 9 | 10 | #Enter payment cvv 11 | MY_CVV= 12 | 13 | #Enter listing url 14 | LISTING_URL= -------------------------------------------------------------------------------- /scripts/gamestop/utils.js: -------------------------------------------------------------------------------- 1 | let selectors = new Map(); 2 | 3 | selectors.set('singin_selector_1', 'body > div.page > div.main-header-container.sticky-header-redesign > header > nav > div.header.container.header-redesign > div > div.header-options.col-3.col-lg-auto > div.account-header > div.header-account-options.tulsa-acclink-toggle'); 4 | selectors.set('singin_selector_2', '#signIn'); 5 | selectors.set('email_selector', '#login-form-email'); 6 | selectors.set('password_selector', '#login-form-password'); 7 | selectors.set('singin_selector_3', '#signinCheck > button'); 8 | selectors.set('pickUp_bttn_selector', '#primary-details > div.primary-details-row > div.cart-and-ipay.divider-line.no-border-mobile > div.add-to-cart-buttons.tulsa-atcbutton-toggle > div > div:nth-child(1) > button'); 9 | selectors.set('cart_inventory_selector', 'body > div.page > div.main-header-container.sticky-header-redesign > header > nav > div.header.container.header-redesign > div > div.header-options.col-3.col-lg-auto > div.tulsa-minicart-toggle > div > div > div.minicart-total.hide-link-med > a > span.minicart-quantity'); 10 | selectors.set('change_store_selector', 'body > div.page > div.main-header-container.sticky-header-redesign > div > div > div > div.header-banner-utils.col-auto > div.tulsa-custlookup-toggle > div > a > span.store-name.d-none.d-lg-inline'); 11 | selectors.set('zip_input_selector', '#store-search-input'); 12 | selectors.set('pick_store_selector', '#ae-main-content > div.store-locator-search-stores-container > div > div'); 13 | selectors.set('chekout_bttn_selector_1', '#ae-main-content > div.row.cart-rd.container.m-0.p-0 > div.col-12.col-lg-3.totals.cart-rd.mt-3.mt-lg-0 > div.row.p-2.bg-white.mb-3 > div.col-12.checkout-continue-redesign.p-0.tulsa-checkoutbutton-toggle > div > a > span.checkout-btn-text-mobile'); 14 | selectors.set('chekout_bttn_selector_2', '#checkout-main > div.row.no-gutters.next-step-button.justify-content-center.workflow-button > div > div > div > button.btn.btn-primary.btn-block.submit-shipping'); 15 | selectors.set('cvv_bttn_selector', '#saved-payment-security-code'); 16 | selectors.set('chekout_bttn_selector_3', '#checkout-main > div:nth-child(2) > div.col-12.col-lg-9.mb-lg-2.left-section > div.row.no-gutters.order-summary.justify-content-end > div > div > div > div.next-step-summary-button > button.btn.btn-primary.btn-block.submit-payment'); 17 | selectors.set('place_order_selector', '#checkout-main > div:nth-child(2) > div.col-12.col-lg-3.order-summary-section.right-rail > div:nth-child(1) > div.card-body.order-total-summary > div.next-step-summary-button > form > button'); 18 | 19 | 20 | module.exports = { 21 | selectors, 22 | } -------------------------------------------------------------------------------- /scripts/microcenter/README.md: -------------------------------------------------------------------------------- 1 | # Special handling.. 2 | # About Microcenter puppet purchase bot 3 | 4 | __For the best experience while using microcenter puppeteer workflow, be sure to add all necesarry account info such as phone number, located in Account > Profile > Update Account Information. Anything that is required for checkout should then be added to the .env.userInfo file__ 5 | 6 | The Microcenter website has a captcha puzzle when login in, which this program has no way of handling. To get around this, the bot uses google single-signin. 7 | This means that additional email credentials are required in order for the puppeteer to signin to the Microcenter account. 8 | Rememeber to fill in all required information inside _**scripts/< bot >/userInfo/.env.userInfo**_ 9 | 10 | # Usage: 11 | 12 | Microcenter bot requires specifying the users desired store within the LISTING_URL or TEST_USER_LISTING_URL environment variables. 13 | # EXAMPLE; 14 | TEST_USER_LISTING_URL=https://www.microcenter.com/product/600551/seagate-barracuda-2tb-7200rpm-sata-iii-6gb-s-35-internal-hard-drive/_**?storeid=121**_ 15 | 16 | CA - Tustin = 101 17 | CO - Denver = 181 18 | GA - Duluth = 065 19 | GA - Marietta = 041 20 | IL - Chicago = 151 21 | IL - Westmont = 025 22 | KS - Overland Park = 191 23 | MA - Cambridge = 121 24 | MD - Rockville = 085 25 | MD - Parkville = 125 26 | MI - Madison Heights = 055 27 | MN - St. Louis Park = 045 28 | MO - Brentwood = 095 29 | NJ - North Jersey = 075 30 | NY - Westbury = 171 31 | NY - Brooklyn = 115 32 | NY - Flushing = 145 33 | NY - Yonkers = 105 34 | OH - Columbus = 141 35 | OH - Mayfield Heights = 051 36 | OH - Sharonville = 071 37 | PA - St. Davids = 061 38 | TX - Houston = 155 39 | TX - Dallas = 131 40 | VA - Fairfax = 081 41 | 42 | 43 | ### Testing 44 | 45 | When running the newegg bot multtiple times, its required that the last security code email be deleted. Currently working on having newegg bot do this automatically. 46 | 47 | ### Don't forget, Options 48 | 49 | As of now I have not found a way to get around the capcha puzzle, or not being able to pre-define a store in the account setup ( only a matter of time before I do! ). 50 | 51 | Don't feel like this bot lives up to your expectations ??? No problem ! Please find one of the other scripts in this repo :) -------------------------------------------------------------------------------- /scripts/microcenter/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$USER_ENV" ] 4 | then 5 | export USER_ENV=userInfo 6 | else 7 | export USER_ENV=$USER_ENV 8 | fi 9 | echo "Environmnet: $USER_ENV\_environment" 10 | 11 | USER_ENV=$USER_ENV node scripts/microcenter/micro-bot.js -------------------------------------------------------------------------------- /scripts/microcenter/micro-bot.js: -------------------------------------------------------------------------------- 1 | const taskHandler = require('./taskHandler'); 2 | const myInfo = require('./myInfo'); 3 | const utils = require('./utils'); 4 | const Spinner = require('cli-spinner'); 5 | const puppeteer = require('puppeteer'); 6 | const colors = require('colors'); 7 | 8 | async function addToCart(page) { 9 | await page.waitForTimeout(500); 10 | await page.$eval(utils.selectors.get('add_to_cart_selector'), (el) => el.click()); 11 | 12 | console.log('Item added to cart ..'); 13 | await page.screenshot({ path: `${myInfo.snapShotPath}+added_to_cart.png` }); 14 | } 15 | 16 | async function microcenterBot() { 17 | // Spinner 18 | var mySpinner = new Spinner.Spinner('processing.. %s'); 19 | mySpinner.setSpinnerString('|/-\\'); 20 | mySpinner.start(); 21 | 22 | try { 23 | let launcherArgs; 24 | let pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 25 | if (process.env.USER_ENV === 'testUserInfo') { 26 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', `--window-size=750,750`]; 27 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 28 | } else { 29 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 30 | } 31 | 32 | // Start of test: Launch and go to login website 33 | const browser = await puppeteer.launch({ 34 | defaultViewport: null, 35 | headless: false, // not sure about running headless.. Bot detection. 36 | args: launcherArgs, 37 | executablePath: pathToBrowser, 38 | }); 39 | 40 | const page = await browser.newPage(); 41 | await page.setDefaultNavigationTimeout(0); 42 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 43 | await page.goto('https://www.microcenter.com', { waitUntil: 'networkidle2' }); 44 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 45 | 46 | // Signing in 47 | await taskHandler.logIn(browser, page); 48 | 49 | // TESTING - Comment out when done. 50 | // await cleanUpAccount(page); 51 | // For cleaning up account/pause program - usefull for test setup 52 | // await page.waitForTimeout(9000000); 53 | 54 | // Navigate to listing & add to cart 55 | let amountOrdered = 0; 56 | while (amountOrdered < 1) { 57 | 58 | console.log('\n[1/4] .. Navigating to listing page ..'.bgBlue); 59 | console.log(`${myInfo.listingURL}`); 60 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 61 | await page.goto(`${myInfo.listingURL}`, { waitUntil: 'networkidle2' }); 62 | await page.screenshot({ path: `${myInfo.snapShotPath}+listing_page.png` }); 63 | 64 | // Checking to see if listing is out of stock 65 | await page.waitForSelector(utils.selectors.get('inventory_count')); 66 | let stocks = await page.$eval(utils.selectors.get('inventory_count'), (element) => { return element.innerText }); 67 | let isOutOfStock = stocks.includes("SOLD OUT"); 68 | console.log('isOutOfStock: ' + `${isOutOfStock}`.red); 69 | 70 | // While listing is out of stock: Change store, check availability 71 | let testRuns = 0; 72 | while (isOutOfStock) { 73 | console.log('\nOUT OF STOCK'.red); 74 | console.log('\nRefreshing Page..'.yellow); 75 | await page.reload(); 76 | 77 | // Check if current store has listing 78 | await page.waitForTimeout(500); 79 | await page.waitForSelector(utils.selectors.get('inventory_count')); 80 | inventoryText = await page.$eval(utils.selectors.get('inventory_count'), (element) => { return element.innerText }); 81 | isOutOfStock = inventoryText.includes("SOLD OUT"); 82 | 83 | if ((`${process.env.USER_ENV}` == 'testUserInfo') && (testRuns == 10)) { 84 | testRuns++; 85 | return; 86 | } 87 | } 88 | console.log('\nListing is in stock !!'.bgBlue); 89 | 90 | // Add listing to cart 91 | console.log('\n[2/4] .. Adding item to cart ..'.bgBlue); 92 | await page.waitForTimeout(500); 93 | await addToCart(page); 94 | 95 | // Navigate to cart 96 | console.log('\n[3/4] .. Navigating to cart ..'.bgBlue); 97 | const cartURL = 'https://cart.microcenter.com/cart.aspx'; 98 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 99 | await page.goto(`${cartURL}`, { waitUntil: 'networkidle2' }); 100 | await page.screenshot({ path: `${myInfo.snapShotPath}+nav_to_cart.png` }); 101 | 102 | //Checkout listing 103 | console.log('\n[4/4] .. Checking out cart ..'.bgBlue); 104 | await taskHandler.checkoutCart(page); 105 | 106 | // Ctrl+C && Celebrate 107 | console.log('\nDone. Goteee boiiis!!! \n'.rainbow); 108 | console.log('\nCtrl+C && Celebrate \n'.bgRed); 109 | 110 | // Done 111 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 112 | await page.goto('https://www.tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254', { waitUntil: 'networkidle2' }); 113 | amountOrdered++; 114 | } 115 | await page.waitForTimeout(7000); 116 | await page.close(); 117 | await browser.close(); 118 | await mySpinner.stop(); 119 | await process.exit(); 120 | return; 121 | } catch (error) { 122 | console.log('\n' + error); 123 | throw error; 124 | } finally { 125 | 126 | } 127 | } 128 | 129 | 130 | microcenterBot(); -------------------------------------------------------------------------------- /scripts/microcenter/myInfo.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: `scripts/microcenter/user_info/.env.${process.env.USER_ENV}`}); 2 | var date = new Date(); 3 | var timeStamp = `${process.env.USER_ENV}_${date.getMonth()}-${date.getDay()}_${Math.floor(Math.random() * 100001)}`; 4 | let snapShotPath = 'record/screen_shots/microcenter/' + `${timeStamp}`; 5 | 6 | let myemail; 7 | let myInboxPass 8 | let myphone; 9 | let myloc; 10 | let mycvv; 11 | let listingURL; 12 | 13 | if (`${process.env.USER_ENV}` === 'testUserInfo') { 14 | myemail = process.env.TEST_USER_EMAIL; 15 | myInboxPass = process.env.TEST_USER_INBOX_PASSW; 16 | myphone = process.env.TEST_USER_PHONE; 17 | myloc = process.env.TEST_USER_LOC; 18 | mycvv = process.env.TEST_USER_CVV; 19 | listingURL = process.env.TEST_USER_LISTING_URL; 20 | } else { 21 | myemail = process.env.MY_EMAIL; 22 | myInboxPass = process.env.MY_INBOX_PASSW; 23 | myphone = process.env.MY_PHONE_NUMBER; 24 | myloc = process.env.MY_LOC; 25 | mycvv = process.env.MY_CVV; 26 | listingURL = process.env.LISTING_URL; 27 | } 28 | 29 | module.exports = { 30 | myemail, 31 | myInboxPass, 32 | mycvv, 33 | myloc, 34 | listingURL, 35 | snapShotPath, 36 | }; -------------------------------------------------------------------------------- /scripts/microcenter/taskHandler.js: -------------------------------------------------------------------------------- 1 | const Spinner = require("cli-spinner"); 2 | const colors = require("colors"); 3 | const myInfo = require("./myInfo"); 4 | const utils = require("./utils"); 5 | 6 | async function getNewPageWhenLoaded(browser) { 7 | return new Promise((x) => browser.once('targetcreated', async (target) => { 8 | let newPage = await target.page(); 9 | let newPagePromise = new Promise(() => newPage.once('domcontentloaded', () => x(newPage))); 10 | let isPageLoaded = await newPage.evaluate(() => document.readyState); 11 | return isPageLoaded.match('complete|interactive') ? x(newPage) : newPagePromise; 12 | })); 13 | } 14 | 15 | async function logIn(browser, page) { 16 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 17 | // Navigate to login page 18 | let signingText; 19 | let isSignedout; 20 | 21 | await page.waitForSelector(utils.selectors.get("singin_selector_1")); 22 | signingText = await page.$eval(utils.selectors.get("singin_selector_1"), 23 | (el) => { 24 | return el.innerText; 25 | } 26 | ); 27 | isSignedout = signingText.includes("Sign in"); 28 | console.log("signingText: " + signingText); 29 | console.log("isSignedout: " + isSignedout); 30 | 31 | while (isSignedout) { 32 | console.log('Navigating to signin page ..'.yellow); 33 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 34 | await page.goto('https://account.microcenter.com/Login.aspx', { waitUntil: 'networkidle2' }); 35 | console.log('Signing in ..'.yellow); 36 | 37 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 38 | let newPagePromise = getNewPageWhenLoaded(browser); 39 | await page.$eval(utils.selectors.get("google_signin_selector"), (el) => el.click()); 40 | let newPage = await newPagePromise; 41 | await newPage.screenshot({ path: `${myInfo.snapShotPath}+google_signin_selector.png` }); 42 | 43 | // Enter login credentials & signin 44 | await newPage.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 45 | //email 46 | await newPage.$eval(utils.selectors.get('inbox_email_selector'), (el) => el.click()); 47 | await newPage.type(utils.selectors.get('inbox_email_selector'), myInfo.myemail, {delay: 100}); 48 | await newPage.$eval(utils.selectors.get('singin_selector_2'), (el) => el.click()); 49 | 50 | //password 51 | await newPage.waitForTimeout(3400); 52 | await newPage.$eval(utils.selectors.get('inbox_password_selector'), (el) => el.click()); 53 | await newPage.type(utils.selectors.get('inbox_password_selector'), myInfo.myInboxPass, {delay: 100}); 54 | await newPage.screenshot({ path: `${myInfo.snapShotPath}+inbox_signin.png` }); 55 | await newPage.$eval(utils.selectors.get('singin_selector_3'), (el) => el.click()); 56 | await newPage.waitForTimeout(20000); 57 | //submit 58 | //await page.waitForTimeout(4000); 59 | //await page.waitForTimeout({ waitUntil: 'networkidle2' }); 60 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_result.png` }); 61 | await page.waitForSelector(utils.selectors.get("singin_selector_1")); 62 | await page.waitForTimeout(4000); // Give time for inner text to show up 63 | signingText = await page.$eval(utils.selectors.get("singin_selector_1"), 64 | (el) => { 65 | return el.innerText; 66 | } 67 | ); 68 | isSignedout = signingText.includes("Sign in"); 69 | 70 | console.log("signingText: " + signingText); 71 | console.log("isSignedout: " + isSignedout); 72 | } 73 | 74 | await page.waitForTimeout(1000); 75 | console.log("Signed in succesfully ..".yellow); 76 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_success.png` }); 77 | } 78 | 79 | async function checkoutCart(page) { 80 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 81 | 82 | await page.$eval(utils.selectors.get("chekout_bttn_selector_1"), (el) => 83 | el.click() 84 | ); 85 | await page.waitForTimeout(500); 86 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_arrive.png` }); 87 | 88 | // Input phone if required.. 89 | // Users should have that filled on their online accounts 90 | // Not going to program for this step 91 | 92 | // Input credit-card cvv 93 | await page.waitForSelector(utils.selectors.get("chekout_bttn_selector_2")); 94 | if ((await page.$(utils.selectors.get("cvv_bttn_selector"))) !== null) { 95 | await page.$eval(utils.selectors.get("cvv_bttn_selector"), (el) => 96 | el.click() 97 | ); 98 | await page.type(utils.selectors.get("cvv_bttn_selector"), myInfo.mycvv); 99 | await page.screenshot({ path: `${myInfo.snapShotPath}+cvv_added.png` }); 100 | } 101 | 102 | // Checkout = 'Moment of truth..'; 103 | await page.focus(utils.selectors.get("chekout_bttn_selector_2")); 104 | //SKIP IF RUNNING TEST 105 | if (`${process.env.USER_ENV}` == "userInfo" ) { 106 | await page.keyboard.press('Enter'); 107 | } 108 | await page.waitForTimeout(7000); 109 | await page.screenshot({ path: `${myInfo.snapShotPath}+result_page.png` }); 110 | } 111 | 112 | module.exports = { 113 | logIn, 114 | checkoutCart, 115 | }; 116 | -------------------------------------------------------------------------------- /scripts/microcenter/user_info/.env.userInfo: -------------------------------------------------------------------------------- 1 | #Enter email 2 | MY_EMAIL= 3 | 4 | #Enter password 5 | MY_INBOX_PASSW= 6 | 7 | #Enter zip code 8 | MY_LOC= 9 | 10 | #Enter payment cvv 11 | MY_CVV= 12 | 13 | #Enter listing url 14 | LISTING_URL= -------------------------------------------------------------------------------- /scripts/microcenter/utils.js: -------------------------------------------------------------------------------- 1 | let selectors = new Map(); 2 | selectors.set('singin_selector_1', '#utility'); 3 | selectors.set('google_signin_selector', '#ctl00_ContentLeftSide_ucLogin_pnlExternalLogin > div.oam_loginReturningLine > div.google-login'); 4 | selectors.set('inbox_email_selector', 'input#identifierId.whsOnd.zHQkBf'); 5 | selectors.set('inbox_password_selector', 'input.whsOnd.zHQkBf'); 6 | selectors.set('singin_selector_2', '#identifierNext > div > button'); 7 | selectors.set('singin_selector_3', 'button.VfPpkd-LgbsSe.VfPpkd-LgbsSe-OWXEXe-k8QpJ.VfPpkd-LgbsSe-OWXEXe-dgl2Hf.nCP5yc.AjY5Oe.DuMIQc.qIypjc.TrZEUc'); 8 | selectors.set('inventory_count', '#pnlInventory > p'); 9 | selectors.set('add_to_cart_selector', '#options-button > form > input.btn-add.grey.big.STBTN'); 10 | selectors.set('chekout_bttn_selector_1', '#ContentPlaceHolder1_ucOrderSummary_lbCheckout'); 11 | selectors.set('grand_total_selector', '#ucOrderSummary_pnlSummary > div > div:nth-child(2) > div'); 12 | selectors.set('phone_number_input_selector', '#ucCheckOut_rlvBillingAddress_ctrl0_txtPhoneNumber'); 13 | selectors.set('review_bttn_selector', '#ucCheckOut_btnContinue'); 14 | selectors.set('chekout_bttn_selector_2', '#ucOrderSummary_lbSubmitOrder'); 15 | selectors.set('cvv_bttn_selector', '#ucCheckOut_txtCCCsv'); 16 | 17 | module.exports = { 18 | selectors, 19 | } -------------------------------------------------------------------------------- /scripts/newegg/README.md: -------------------------------------------------------------------------------- 1 | # Special handling.. 2 | # About Newegg puppet purchase bot 3 | 4 | __For the best experience while using newegg puppeteer workflow, be sure to add all necesarry account info , located in MyAccount > Account Settings. Anything that is required for checkout should then be added to the .env.userInfo file__ 5 | 6 | Newegg website required that you enter a 6 pin security code - ***sent to the email attempting to loggin.*** 7 | This means that additional email credentials are required in order for the puppeteer to retrieve the security code from the email adress. 8 | Rememeber to fill in all required information inside _**scripts/< bot >/userInfo/.env.userInfo**_ 9 | 10 | ### Testing 11 | 12 | When running the newegg bot multtiple times, its required that the last security code email be deleted. Currently working on having newegg bot do this automatically. 13 | 14 | ### Don't forget, Options 15 | 16 | As of now I have not found a way to get around the 6 pin security code (only a matter of time before I do). 17 | 18 | Not comfortable with inputing your email credentials into a random scripts found online ??? No problem ! Please find one of the other scripts in this repo :) -------------------------------------------------------------------------------- /scripts/newegg/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$USER_ENV" ] 4 | then 5 | export USER_ENV=userInfo 6 | else 7 | export USER_ENV=$USER_ENV 8 | fi 9 | echo "Environment: $USER_ENV\_environment" 10 | 11 | USER_ENV=$USER_ENV node scripts/newegg/newegg-bot.js -------------------------------------------------------------------------------- /scripts/newegg/myInfo.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: `scripts/newegg/user_info/.env.${process.env.USER_ENV}` }); 2 | var date = new Date(); 3 | var timeStamp = `${process.env.USER_ENV}_${date.getMonth()}-${date.getDay()}_${Math.floor(Math.random() * 100001)}`; 4 | let snapShotPath = 'record/screen_shots/newegg/' + `${timeStamp}`; 5 | 6 | let myemail; 7 | let mypassw; 8 | let myInboxPass; 9 | let myloc; 10 | let mycvv; 11 | let listingURL; 12 | 13 | if (`${process.env.USER_ENV}` === 'testUserInfo') { 14 | myemail = process.env.TEST_USER_EMAIL; 15 | mypassw = process.env.TEST_USER_PASSW; 16 | myInboxPass = process.env.TEST_USER_INBOX_PASSW; 17 | myloc = process.env.TEST_USER_LOC; 18 | mycvv = process.env.TEST_USER_CVV; 19 | listingURL = process.env.TEST_USER_LISTING_URL; 20 | } else { 21 | myemail = process.env.MY_EMAIL; 22 | mypassw = process.env.MY_PASSW; 23 | myInboxPass = process.env.MY_INBOX_PASSW; 24 | myloc = process.env.MY_LOC; 25 | mycvv = process.env.MY_CVV; 26 | listingURL = process.env.LISTING_URL; 27 | } 28 | 29 | module.exports = { 30 | myemail, 31 | myInboxPass, 32 | myloc, 33 | mycvv, 34 | listingURL, 35 | snapShotPath, 36 | }; 37 | -------------------------------------------------------------------------------- /scripts/newegg/newegg-bot.js: -------------------------------------------------------------------------------- 1 | const Spinner = require('cli-spinner'); 2 | const puppeteer = require('puppeteer'); 3 | const colors = require('colors'); 4 | const taskHandler = require('./taskHandler'); 5 | const myInfo = require('./myInfo'); 6 | const utils = require('./utils'); 7 | 8 | async function neweggBot() { 9 | // Spinner 10 | var mySpinner = new Spinner.Spinner('processing.. %s'); 11 | mySpinner.setSpinnerString('|/-\\'); 12 | mySpinner.start(); 13 | 14 | try { 15 | let launcherArgs; 16 | let pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 17 | if (process.env.USER_ENV === 'testUserInfo') { 18 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', '--disable-setuid-sandbox', `--window-size=1025,1025`]; 19 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 20 | } else { 21 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 22 | } 23 | 24 | // Start of test: Launch and go to login website 25 | const browser = await puppeteer.launch({ 26 | defaultViewport: null, 27 | headless: false, // not sure about running headless.. Bot detection. 28 | args: launcherArgs, 29 | executablePath: pathToBrowser, 30 | }); 31 | 32 | const page = await browser.newPage(); 33 | await page.setDefaultNavigationTimeout(0); 34 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 35 | await page.goto('https://www.newegg.com', { waitUntil: 'networkidle2' }); 36 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 37 | 38 | // Login 39 | await taskHandler.logIn(page); 40 | await page.waitForSelector('div.nav-complex-title'); 41 | 42 | let amountOrdered = 0; 43 | while (amountOrdered < 1) { 44 | 45 | console.log('\n[1/4] .. Navigating to listing page ..'.bgBlue); 46 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 47 | await page.goto(`${myInfo.listingURL}`, { waitUntil: 'networkidle2' }); 48 | console.log(`${myInfo.listingURL}`); 49 | await page.screenshot({ path: `${myInfo.snapShotPath}+listing_page.png` }); 50 | 51 | // Checking to see if listing is out of stock 52 | await page.waitForSelector(utils.selectors.get('outOfStock_selector')); 53 | let inventoryText = await page.$eval(utils.selectors.get('outOfStock_selector'), (element) => { return element.innerHTML }); 54 | let isOutOfStock = inventoryText.includes('OUT OF STOCK'); 55 | console.log('isOutOfStock: ' + `${isOutOfStock}`.red); 56 | 57 | // While listing is out of stock: Refresh page, check availability 58 | let testRuns = 0; 59 | while (isOutOfStock) { // reversing the logic for now, will create new variable for stock selector 60 | console.log('\nOUT OF STOCK'.red); 61 | console.log('\nRefreshing Page..'.yellow); 62 | await page.reload(); 63 | 64 | // Check if current store has listing 65 | await page.waitForTimeout(500); 66 | await page.waitForSelector(utils.selectors.get('outOfStock_selector')); 67 | inventoryText = await page.$eval(utils.selectors.get('outOfStock_selector'), (element) => { return element.innerHTML }); 68 | isOutOfStock = inventoryText.includes('OUT OF STOCK'); 69 | 70 | if ((`${process.env.USER_ENV}` == 'testUserInfo' && testRuns == 10)) { 71 | testRuns++; 72 | return; 73 | } 74 | 75 | } 76 | console.log('\nListing is in stock !!'.bgBlue); 77 | 78 | // Add listing to cart 79 | console.log('\n[2/4] .. Adding item to cart ..'.bgBlue); 80 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 81 | await page.waitForSelector(utils.selectors.get('pickUp_bttn_selector')); 82 | //let pickUp_bttn = await page.$$(utils.selectors.get('pickUp_bttn_selector')); 83 | await page.waitForSelector(utils.selectors.get('chekout_bttn_selector_1')); 84 | await page.focus(utils.selectors.get('chekout_bttn_selector_1')); 85 | await page.keyboard.press('Enter'); 86 | 87 | //await pickUp_bttn[0].click(); 88 | //await page.waitForTimeout(500); 89 | await page.waitForTimeout({ waitUntil: 'networkidle2' }); 90 | console.log('Item added to cart ..'); 91 | await page.screenshot({ path: `${myInfo.snapShotPath}+added_to_cart.png` }); 92 | 93 | // Navigate to cart 94 | console.log('\n[3/4] .. Navigating to cart ..'.bgBlue); 95 | const cartURL = 'https://secure.newegg.com/shop/cart'; 96 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 97 | await page.goto(`${cartURL}`); 98 | await page.waitForTimeout(500); 99 | await page.screenshot({ path: `${myInfo.snapShotPath}+nav_to_cart.png` }); 100 | 101 | //Checkout listing 102 | console.log('\n[4/4] .. Checking out cart ..'.bgBlue); 103 | await taskHandler.checkoutCart(page); 104 | 105 | // Ctrl+C && Celebrate 106 | console.log('\nDone. Goteee boiiis!!! \n'.rainbow); 107 | console.log('\nCtrl+C && Celebrate \n'.bgRed); 108 | 109 | // Done 110 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 111 | await page.goto('https://www.tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254', { waitUntil: 'networkidle2' }); 112 | amountOrdered++; 113 | } 114 | await page.waitForTimeout(7000); 115 | await page.close(); 116 | await browser.close(); 117 | await mySpinner.stop(); 118 | await process.exit(); 119 | return; 120 | } catch (error) { 121 | // expected output: ReferenceError: nonExistentFunction is not defined 122 | // Note - error messages will vary depending on browser 123 | console.log('\n' + error); 124 | } finally { 125 | 126 | } 127 | 128 | } 129 | 130 | neweggBot(); -------------------------------------------------------------------------------- /scripts/newegg/taskHandler.js: -------------------------------------------------------------------------------- 1 | const Spinner = require('cli-spinner'); 2 | const puppeteer = require('puppeteer'); 3 | const colors = require('colors'); 4 | const myInfo = require('./myInfo'); 5 | const utils = require('./utils'); 6 | 7 | async function getSecutiryCode() { 8 | let securityCode; 9 | 10 | let launcherArgs; 11 | let pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 12 | if (process.env.USER_ENV === 'testUserInfo') { 13 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', '--disable-setuid-sandbox', `--window-size=700,700`]; 14 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 15 | } else { 16 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 17 | } 18 | 19 | const browser = await puppeteer.launch({ 20 | defaultViewport: null, 21 | headless: false, 22 | args: launcherArgs, 23 | executablePath: pathToBrowser, 24 | }); 25 | 26 | 27 | // Navigate to email. 28 | const page = await browser.newPage(); 29 | await page.setDefaultNavigationTimeout(0); 30 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 31 | await page.goto('https://www.gmail.com', { waitUntil: 'networkidle2' }); 32 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 33 | 34 | // Enter login credentials & signin 35 | // Email 36 | await page.$eval(utils.selectors.get('inbox_email_selector'), (el) => el.click()); 37 | await page.type(utils.selectors.get('inbox_email_selector'), myInfo.myemail, { delay: 100 }); 38 | await page.$eval(utils.selectors.get('inbox_singin_selector'), (el) => el.click()); 39 | await page.screenshot({ path: `${myInfo.snapShotPath}+inboxEmail.png` }); 40 | 41 | // Password 42 | await page.waitForTimeout(3000); 43 | await page.$eval(utils.selectors.get('inbox_password_selector'), (el) => el.click()); 44 | await page.type(utils.selectors.get('inbox_password_selector'), myInfo.myInboxPass, { delay: 100 }); 45 | await page.$eval(utils.selectors.get('inbox_singin_selector'), (el) => el.click()); 46 | await page.screenshot({ path: `${myInfo.snapShotPath}+inboxPass.png` }); 47 | 48 | await page.waitForTimeout({ waitUntil: 'networkidle2' }); 49 | 50 | // Select email 51 | await page.waitForSelector(utils.selectors.get('inbox_selector')); 52 | await page.$eval(utils.selectors.get('inbox_selector'), (el) => el.click()); 53 | 54 | await page.waitForSelector(utils.selectors.get('securityCode_selector')); 55 | await page.waitForTimeout(5000); // 5 seconds 56 | securityCode = await page.$eval(utils.selectors.get('securityCode_selector'), (element) => { return element.innerHTML }); 57 | await page.screenshot({ path: `${myInfo.snapShotPath}+securityCode.png` }); 58 | 59 | // Delete email 60 | if (`${process.env.USER_ENV}` == "testUserInfo" ) { 61 | await page.focus(utils.selectors.get('delete_email_selector')); 62 | await page.keyboard.press('Enter'); 63 | await page.waitForTimeout(2000); 64 | await page.screenshot({ path: `${myInfo.snapShotPath}+email_deleted.png` }); 65 | } 66 | 67 | let pages = await browser.pages(); 68 | await Promise.all(pages.map(page =>page.close())) 69 | await browser.close(); 70 | 71 | console.log('Security Code: ' + securityCode); 72 | return securityCode; 73 | } 74 | 75 | async function logIn(page) { 76 | // Navigate to login page 77 | console.log('Signing in ..'.yellow); 78 | await page.waitForSelector('div.nav-complex-title'); 79 | await page.$eval('div.nav-complex-title', (el) => el.click()); 80 | 81 | // Enter login credentials & signin 82 | //email 83 | await page.waitForSelector(utils.selectors.get('email_selector')); 84 | await page.$eval(utils.selectors.get('email_selector'), (el) => el.click()); 85 | await page.type(utils.selectors.get('email_selector'), myInfo.myemail); 86 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_submit.png` }); 87 | //submit 88 | await page.focus(utils.selectors.get('singin_selector_1')); 89 | await page.waitForTimeout(1500); // wait for domdocument to lead 90 | await page.keyboard.press('Enter'); 91 | 92 | // Getting security code 93 | const securityCode = await getSecutiryCode(); 94 | 95 | //security code 96 | await page.$eval(utils.selectors.get('securityCode_input_selector'), (el) => el.click()); 97 | await page.type(utils.selectors.get('securityCode_input_selector'), securityCode, { delay: 100 }); 98 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_submit.png` }); 99 | //submit 100 | await page.$eval(utils.selectors.get('singin_selector_1'), (el) => el.click()); 101 | await page.waitForTimeout(500); 102 | console.log('Signed in succesfully ..'.yellow); 103 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_success.png` }); 104 | } 105 | 106 | async function checkoutCart(page) { 107 | //Begin Checkout 108 | await page.$eval(utils.selectors.get('chekout_bttn_selector_1'), (el) => el.click()); 109 | await page.waitForTimeout(500); 110 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_start.png` }); 111 | 112 | //shipping 113 | await page.waitForSelector(utils.selectors.get('checkout_bttns')); 114 | let bttns = await page.$$(utils.selectors.get('checkout_bttns')); 115 | await page.waitForTimeout(800); 116 | 117 | await bttns[0].click(); 118 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_shipping.png` }); 119 | console.log('Done w. shipping'); 120 | 121 | //delivery 122 | await page.waitForTimeout(1000); 123 | await bttns[1].click(); 124 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_shipping.png` }); 125 | console.log('Done w. Delivery'); 126 | 127 | // Input credit-card cvv 128 | await page.waitForTimeout(1000); 129 | if (await page.$(utils.selectors.get('cvv_bttn_selector')) !== null){ 130 | await page.$eval(utils.selectors.get('cvv_bttn_selector'), (el) => el.click()); 131 | await page.type(utils.selectors.get('cvv_bttn_selector'), myInfo.mycvv); 132 | await page.screenshot({ path: `${myInfo.snapShotPath}+cvv_added.png` }); 133 | } 134 | // Review card card-add-new 135 | await page.waitForTimeout(800); 136 | await bttns[2].click(); 137 | await page.screenshot({ path: `${myInfo.snapShotPath}+review_page.png` }); 138 | console.log('Done w. Review'); 139 | 140 | let checkout = 'Moment of truth..'; 141 | await page.waitForSelector(utils.selectors.get('placeOrder_selector')); 142 | await page.focus(utils.selectors.get('placeOrder_selector')); 143 | //SKIP IF RUNNING TEST 144 | if (`${process.env.USER_ENV}` == "userInfo" ) { 145 | await page.keyboard.press('Enter'); 146 | } 147 | await page.waitForTimeout(7000); 148 | await page.screenshot({ path: `${myInfo.snapShotPath}+result_page.png` }); 149 | console.log(checkout); 150 | } 151 | 152 | module.exports = { 153 | logIn, 154 | checkoutCart, 155 | } -------------------------------------------------------------------------------- /scripts/newegg/user_info/.env.userInfo: -------------------------------------------------------------------------------- 1 | #Enter email 2 | MY_EMAIL= 3 | 4 | #Enter email password 5 | MY_INBOX_PASSW= 6 | 7 | #Enter zip code 8 | MY_LOC= 9 | 10 | #Enter payment cvv 11 | MY_CVV= 12 | 13 | #Enter listing url 14 | LISTING_URL= -------------------------------------------------------------------------------- /scripts/newegg/utils.js: -------------------------------------------------------------------------------- 1 | let selectors = new Map(); 2 | selectors.set('pickUp_bttn_selector', '#ProductBuy > div > div:nth-child(2) > button'); 3 | selectors.set('outOfStock_selector', 'div.product-inventory'); 4 | selectors.set('securityCode_selector', 'div:nth-child(2) > table > tbody > tr > td > table > tbody > tr:nth-child(1) > td > table > tbody > tr:nth-child(2) > td > table > tbody > tr > td > table > tbody > tr:nth-child(4) > td'); 5 | selectors.set('delete_email_selector', 'div > div.iH.bzn > div > div:nth-child(2) > div.T-I.J-J5-Ji.nX.T-I-ax7.T-I-Js-Gs.mA > div'); 6 | selectors.set('securityCode_input_selector', 'div.form-v-code input'); 7 | selectors.set('inbox_selector', 'html body div div div div div div div div div div div div div div div div div div div table tbody tr'); 8 | selectors.set('inbox_singin_selector', 'button.VfPpkd-LgbsSe.VfPpkd-LgbsSe-OWXEXe-k8QpJ.VfPpkd-LgbsSe-OWXEXe-dgl2Hf.nCP5yc.AjY5Oe.DuMIQc.qIypjc.TrZEUc'); 9 | selectors.set('inbox_email_selector', 'input#identifierId.whsOnd.zHQkBf'); 10 | selectors.set('inbox_password_selector', 'input.whsOnd.zHQkBf'); 11 | selectors.set('singin_selector_1', 'button#signInSubmit.btn.btn-orange'); 12 | selectors.set('email_selector', 'input#labeled-input-signEmail'); 13 | selectors.set('password_selector', 'input#password.sc-iwsKbI.eAChmV.sc-kIPQKe.frLPpE'); 14 | selectors.set('chekout_bttn_selector_1', 'button.btn.btn-primary.btn-wide'); 15 | selectors.set('checkout_bttns', 'button.btn.btn-primary.checkout-step-action-done.layout-quarter'); 16 | selectors.set('cvv_bttn_selector', 'input.form-text.mask-cvv-4'); 17 | selectors.set('placeOrder_selector', 'button#btnCreditCard.btn.btn-primary.btn-wide'); 18 | 19 | module.exports = { 20 | selectors, 21 | } -------------------------------------------------------------------------------- /scripts/target/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$USER_ENV" ] 4 | then 5 | export USER_ENV=userInfo 6 | else 7 | export USER_ENV=$USER_ENV 8 | fi 9 | echo "Environmnet: $USER_ENV\_environment" 10 | 11 | USER_ENV=$USER_ENV node scripts/target/target-bot.js 12 | 13 | exit -------------------------------------------------------------------------------- /scripts/target/myInfo.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: `scripts/target/user_info/.env.${process.env.USER_ENV}`}); 2 | var date = new Date(); 3 | var timeStamp = `${process.env.USER_ENV}_${date.getMonth()}-${date.getDay()}_${Math.floor(Math.random() * 100001)}`; 4 | let snapShotPath = 'record/screen_shots/target/' + `${timeStamp}`; 5 | 6 | let myemail; 7 | let mypassw; 8 | let myloc; 9 | let mycvv; 10 | let listingURL; 11 | 12 | if (`${process.env.USER_ENV}` === 'testUserInfo') { 13 | myemail = process.env.TEST_USER_EMAIL; 14 | mypassw = process.env.TEST_USER_PASSW; 15 | myloc = process.env.TEST_USER_LOC; 16 | mycvv = process.env.TEST_USER_CVV; 17 | listingURL = process.env.TEST_USER_LISTING_URL; 18 | } else { 19 | myemail = process.env.MY_EMAIL; 20 | mypassw = process.env.MY_PASSW; 21 | myloc = process.env.MY_LOC; 22 | mycvv = process.env.MY_CVV; 23 | listingURL = process.env.LISTING_URL; 24 | } 25 | 26 | module.exports = { 27 | myemail, 28 | mypassw, 29 | myloc, 30 | mycvv, 31 | listingURL, 32 | snapShotPath, 33 | }; -------------------------------------------------------------------------------- /scripts/target/target-bot.js: -------------------------------------------------------------------------------- 1 | const taskHandler = require('./taskHandler'); 2 | const myInfo = require('./myInfo'); 3 | const utils = require('./utils'); 4 | const Spinner = require('cli-spinner'); 5 | const puppeteer = require('puppeteer'); 6 | const colors = require('colors'); 7 | 8 | async function addToCart(page) { 9 | await page.$eval(utils.selectors.get('pickUp_bttn_selector'), (el) => el.click()); 10 | console.log('Item added to cart ..'); 11 | await page.waitForTimeout(500); 12 | await page.screenshot({ path: `${myInfo.snapShotPath}+added_to_cart.png` }); 13 | } 14 | 15 | async function targetBot() { 16 | // Spinner 17 | var mySpinner = new Spinner.Spinner('processing.. %s'); 18 | mySpinner.setSpinnerString('|/-\\'); 19 | mySpinner.start(); 20 | 21 | try { 22 | let launcherArgs; 23 | let pathToBrowser; 24 | if (process.env.USER_ENV === 'testUserInfo') { 25 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', '--disable-setuid-sandbox', `--window-size=1025,1025`]; 26 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 27 | } else { 28 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 29 | } 30 | 31 | // Start of test: Launch and go to login website 32 | const browser = await puppeteer.launch({ 33 | defaultViewport: null, 34 | headless: false, // not sure about running headless.. Bot detection. 35 | args: launcherArgs, 36 | executablePath: pathToBrowser, 37 | }); 38 | 39 | const page = await browser.newPage(); 40 | await page.setDefaultNavigationTimeout(0); 41 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 42 | await page.goto('https://www.target.com', { waitUntil: 'networkidle2' }); 43 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 44 | 45 | // Signing in 46 | await taskHandler.logIn(page); 47 | 48 | // TESTING - Comment out when done. 49 | // await cleanUpAccount(page); 50 | // For cleaning up account/pause program - usefull for test setup 51 | // await page.waitForTimeout(9000000); 52 | 53 | // Navigate to listing & add to cart 54 | let amountOrdered = 0; 55 | while (amountOrdered < 1) { 56 | 57 | console.log('\n[1/4] .. Navigating to listing page ..'.bgBlue); 58 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 59 | await page.goto(`${myInfo.listingURL}`, { waitUntil: 'networkidle2' }); 60 | console.log(`${myInfo.listingURL}`); 61 | await page.screenshot({ path: `${myInfo.snapShotPath}+listing_page.png` }); 62 | 63 | // Checking to see if listing is out of stock 64 | let stocks = await page.$eval( utils.selectors.get("pickUp_bttn_selector"), (element) => { return element.innerHTML }); 65 | let isOutOfStock = stocks.includes('Out of stock'); 66 | console.log('isOutOfStock: ' + `${isOutOfStock}`.red); 67 | 68 | // While listing is out of stock: Change store, check availability 69 | let testRuns = 0; 70 | while (isOutOfStock) { 71 | console.log('\nProduct is OUT OF STOCK'.red); 72 | isOutOfStock = await taskHandler.findListing(page); 73 | 74 | if ((`${process.env.USER_ENV}` == 'testUserInfo' && testRuns == 1)) { 75 | return; 76 | } 77 | testRuns++; 78 | } 79 | console.log('\nListing is in stock !!'.bgBlue); 80 | 81 | // Add listing to cart 82 | console.log('\n[2/4] .. Adding item to cart ..'.bgBlue); 83 | await page.waitForTimeout(500); 84 | await addToCart(page); 85 | 86 | // Navigate to cart 87 | console.log('\n[3/4] .. Navigating to cart ..'.bgBlue); 88 | const cartURL = 'https://www.target.com/co-cart'; 89 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 90 | await page.goto(`${cartURL}`); 91 | await page.waitForTimeout(4000); 92 | await page.screenshot({ path: `${myInfo.snapShotPath}+nav_to_cart.png` }); 93 | 94 | //Checkout listing 95 | console.log('\n[4/4] .. Checking out cart ..'.bgBlue); 96 | await page.waitForTimeout(500); 97 | await taskHandler.checkoutCart(page); 98 | 99 | // Ctrl+C && Celebrate 100 | console.log('\nDone. Goteee boiiis!!! \n'.rainbow); 101 | console.log('\nCtrl+C && Celebrate \n'.bgRed); 102 | 103 | // Done 104 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 105 | await page.goto('https://www.tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254', { waitUntil: 'networkidle2' }); 106 | amountOrdered++; 107 | } 108 | await page.waitForTimeout(7000); 109 | await page.close(); 110 | await browser.close(); 111 | await mySpinner.stop(); 112 | } 113 | catch (err) { 114 | // expected output: ReferenceError: nonExistentFunction is not defined 115 | // Note - error messages will vary depending on browser 116 | 117 | console.log('\n' + err); 118 | throw new Error(err); 119 | } 120 | finally { 121 | 122 | return; 123 | } 124 | } 125 | 126 | targetBot(); -------------------------------------------------------------------------------- /scripts/target/taskHandler.js: -------------------------------------------------------------------------------- 1 | const Spinner = require("cli-spinner"); 2 | const colors = require("colors"); 3 | const myInfo = require("./myInfo"); 4 | const utils = require("./utils"); 5 | 6 | async function logIn(page) { 7 | // Navigate to login page 8 | let signingText; 9 | let isSignedout; 10 | 11 | try { 12 | console.log("Navigating to signin page ..".yellow); 13 | await page.waitForSelector(utils.selectors.get("singin_selector_1")); 14 | signingText = await page.$eval( 15 | "span.styles__AccountName-sc-1kk0q5l-0.iQFCAn", 16 | (el) => { 17 | return el.innerText; 18 | } 19 | ); 20 | isSignedout = signingText === "Sign in"; 21 | console.log("signingText: " + signingText); 22 | console.log("isSignedout: " + isSignedout); 23 | 24 | while (isSignedout) { 25 | await page.$eval(utils.selectors.get("singin_selector_1"), (el) => 26 | el.click() 27 | ); 28 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_page.png` }); 29 | await page.$eval(utils.selectors.get("singin_selector_2"), (el) => 30 | el.click() 31 | ); 32 | await page.screenshot({ path: `${myInfo.snapShotPath}_login_page.png` }); 33 | 34 | // Enter login credentials & signin 35 | //email 36 | console.log("Signing in ..".yellow); 37 | await page.$eval(utils.selectors.get("email_selector"), (el) => el.click()); 38 | await page.type(utils.selectors.get("email_selector"), myInfo.myemail, { delay: 100 }); 39 | 40 | //password 41 | await page.$eval(utils.selectors.get("password_selector"), (el) => 42 | el.click() 43 | ); 44 | await page.type(utils.selectors.get("password_selector"), myInfo.mypassw, { delay: 100 }); 45 | 46 | //submit 47 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_submit.png` }); 48 | await page.$eval(utils.selectors.get("singin_selector_3"), (el) => 49 | el.click() 50 | ); 51 | 52 | await page.waitForTimeout(3000); // Allow text to load 53 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_result.png` }); 54 | 55 | await page.waitForSelector("#account > span.styles__AccountName-sc-1kk0q5l-0.iQFCAn"); 56 | await page.waitForTimeout(400); // Allow text to load 57 | signingText = await page.$eval( 58 | "#account > span.styles__AccountName-sc-1kk0q5l-0.iQFCAn", 59 | (el) => { 60 | return el.innerText; 61 | } 62 | ); 63 | isSignedout = signingText === "Sign in"; 64 | 65 | console.log("signingText: " + signingText); 66 | console.log("isSignedout: " + isSignedout); 67 | } 68 | 69 | await page.waitForTimeout(1000); 70 | console.log("Signed in succesfully ..".yellow); 71 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_success.png` }); 72 | } 73 | catch(err) { 74 | console.log('\n' ); 75 | throw new Error (err); 76 | } 77 | } 78 | 79 | async function findListing(page) { 80 | let stocks; 81 | let isOutOfStock; 82 | 83 | try { 84 | for (let i = 0; i < 5; i++) { 85 | await page.waitForSelector(utils.selectors.get("change_store_selector")); 86 | await page.$eval(utils.selectors.get("change_store_selector"), (el) => 87 | el.click() 88 | ); 89 | await page.waitForTimeout(500); 90 | await page.screenshot({ path: `${myInfo.snapShotPath}+find_store1.png` }); 91 | 92 | await page.$eval(utils.selectors.get("zip_input_selector"), (el) => 93 | el.click() 94 | ); 95 | await page.type(utils.selectors.get("zip_input_selector"), myInfo.myloc); 96 | await page.$eval(utils.selectors.get("lookup_bttn_selector"), (el) => 97 | el.click() 98 | ); 99 | await page.waitForTimeout(500); 100 | await page.screenshot({ path: `${myInfo.snapShotPath}+find_store2.png` }); 101 | 102 | let bttns = await page.$$(utils.selectors.get("pick_store_selector")); 103 | await bttns[i].click(); 104 | await page.waitForTimeout(500); 105 | await page.screenshot({ 106 | path: `${myInfo.snapShotPath}_change_store_${i}.png`, 107 | }); 108 | console.log("\nSwitched Stores".yellow); 109 | 110 | // Check if current store has listing 111 | stocks = await page.$eval( 112 | utils.selectors.get("pickUp_bttn_selector"), 113 | (element) => { 114 | return element.innerHTML; 115 | } 116 | ); 117 | isOutOfStock = stocks.includes("Out of stock"); 118 | console.log("isOutOfStock: " + `${isOutOfStock}`.red); 119 | 120 | // Stop switching stores if listing is found 121 | if (isOutOfStock != true) { 122 | break; 123 | } 124 | } 125 | return isOutOfStock; 126 | } catch(err){ 127 | console.log('\n' + err); 128 | throw err; 129 | } 130 | } 131 | 132 | async function checkoutCart(page) { 133 | try { 134 | await page.waitForSelector(utils.selectors.get("chekout_bttn_selector_1")); 135 | await page.$eval(utils.selectors.get("chekout_bttn_selector_1"), (el) => 136 | el.click() 137 | ); 138 | await page.waitForTimeout(500); 139 | await page.screenshot({ path: `${myInfo.snapShotPath}+checkout_arrive.png` }); 140 | 141 | // Input credit-card cvv 142 | await page.waitForSelector(utils.selectors.get("chekout_bttn_selector_2")); 143 | if ((await page.$(utils.selectors.get("cvv_bttn_selector"))) !== null) { 144 | await page.waitForTimeout(500); 145 | await page.$eval(utils.selectors.get("cvv_bttn_selector"), (el) => 146 | el.click() 147 | ); 148 | await page.type(utils.selectors.get("cvv_bttn_selector"), myInfo.mycvv); 149 | await page.screenshot({ path: `${myInfo.snapShotPath}+cvv_added.png` }); 150 | } 151 | 152 | // Checkout = 'Moment of truth..'; 153 | await page.focus(utils.selectors.get("chekout_bttn_selector_2")); 154 | //SKIP IF RUNNING TEST 155 | if (`${process.env.USER_ENV}` == "userInfo" ) { 156 | await page.keyboard.press('Enter'); 157 | } 158 | await page.waitForTimeout(7000); 159 | await page.screenshot({ path: `${myInfo.snapShotPath}+result_page.png` }); 160 | } 161 | catch(err){ 162 | console.log('\n' + err); 163 | throw err; 164 | } 165 | } 166 | 167 | module.exports = { 168 | logIn, 169 | findListing, 170 | checkoutCart, 171 | }; 172 | -------------------------------------------------------------------------------- /scripts/target/user_info/.env.userInfo: -------------------------------------------------------------------------------- 1 | #Enter email 2 | MY_EMAIL= 3 | 4 | #Enter password 5 | MY_PASSW= 6 | 7 | #Enter zip code 8 | MY_LOC= 9 | 10 | #Enter payment cvv 11 | MY_CVV= 12 | 13 | #Enter listing url 14 | LISTING_URL= -------------------------------------------------------------------------------- /scripts/target/utils.js: -------------------------------------------------------------------------------- 1 | let selectors = new Map(); 2 | selectors.set('pickUp_bttn_selector', 'button.BaseButton-sc-3v3oog-0.ButtonPrimary-sc-9wgfzx-0.styles__StyledPrimaryButton-sc-1f2lsll-0.eVHdWy.JRFKP.bebHXQ'); 3 | selectors.set('outOfStock_selector', '#viewport > div:nth-child(4) > div > div.styles__StyledRow-sc-1nuqtm0-0.cuJjmE > div.styles__StyledCol-ct8kx6-0.fkyjP > div.h-padding-h-default > div.h-display-flex.h-flex-direction-col > div.styles__StyledAvailabilitySneakPeekWrapper-dbsmav-0.fClyma.h-margin-b-tight > span'); 4 | selectors.set('singin_selector_1', 'a#account.Link-sc-1khjl8b-0.kdCHb.AccountLink-gx13jw-1.ePhaOG'); 5 | selectors.set('singin_selector_2', 'div.Row-uds8za-0.glDPjN'); 6 | selectors.set('email_selector', '#username'); 7 | selectors.set('password_selector', '#password'); 8 | selectors.set('singin_selector_3', '#login'); 9 | selectors.set('change_store_selector', '#storeId-utilityNavBtn > div.h-text-bold.h-text-md'); 10 | selectors.set('zip_input_selector', '#zipOrCityState'); 11 | selectors.set('pick_store_selector', 'body > div:nth-child(18) > div > div > div > div > div:nth-child(3) > div.Row-uds8za-0.fdXLni.h-flex-align-center.h-flex-justify-center > div:nth-child(1) > button'); 12 | selectors.set('lookup_bttn_selector', 'body > div:nth-child(18) > div > div > div > div > div:nth-child(1) > div > div.Row-uds8za-0.fdXLni > div.Col-favj32-0.FsLht.h-padding-a-tight.h-text-right > button'); 13 | selectors.set('chekout_bttn_selector_1', 'button.BaseButton-sc-3v3oog-0.ButtonPrimary-sc-9wgfzx-0.cLBbtz.JRFKP'); 14 | selectors.set('cvv_bttn_selector', '#creditCardInput-cvv'); 15 | selectors.set('chekout_bttn_selector_2', '#orderSummaryWrapperDiv > div > div > div.h-padding-h-default.h-bg-white > div > button'); 16 | 17 | module.exports = { 18 | selectors, 19 | } -------------------------------------------------------------------------------- /scripts/test/all-bots-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of all-bots-find-stocks test. ' 3 | echo ' Should run each bot.js script, try to find available stock, then exit:0 ' 4 | 5 | { # try 6 | npm run bestbuy-find-stocks-test 7 | echo ' Finished running bestbuy-bot' 8 | 9 | npm run gamestop-find-stocks-test 10 | echo ' Finished running gamestop-bot' 11 | 12 | npm run micro-find-stocks-test 13 | echo ' Finished running micro-bot' 14 | 15 | npm run newegg-find-stocks-test 16 | echo ' Finished running newegg-bot' 17 | 18 | npm run target-find-stocks-test 19 | echo ' Finished running target-bot' 20 | 21 | npm run walmart-find-stocks-test 22 | echo ' Finished running walmart-bot' 23 | 24 | } || { # catch 25 | # save log for exception 26 | set -e 27 | err_report() { 28 | echo "Error on line $1" 29 | } 30 | trap 'err_report $LINENO' ERR 31 | exit 2 32 | } 33 | 34 | 35 | 36 | 37 | echo 'Done' -------------------------------------------------------------------------------- /scripts/test/all-bots-full-cycle.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of all-bots-fullCycle test. ' 3 | echo ' Should run a full cycle of all bot.js script, then exit: 0 ' 4 | 5 | npm run bestbuy-bot-test 6 | echo ' Finished running bestbuy-bot' 7 | 8 | npm run gamestop-bot-test 9 | echo ' Finished running gamestop-bot' 10 | 11 | npm run micro-bot-test 12 | echo ' Finished running micro-bot' 13 | 14 | npm run newegg-bot-test 15 | echo ' Finished running newegg-bot' 16 | 17 | npm run target-bot-test 18 | echo ' Finished running target-bot' 19 | 20 | npm run walmart-bot-test 21 | echo ' Finished running walmart-bot' 22 | 23 | echo 'Done' -------------------------------------------------------------------------------- /scripts/test/bestbuy-bot.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of bestbuy-bot test ' 3 | echo ' Should run a full cycle of bestbuy-bot.js script, then exit: 0 ' 4 | 5 | USER_ENV=testUserInfo npm run bestbuy-bot 6 | 7 | if [ $? -eq 0 ]; then 8 | 9 | echo 'Finished running bestbuy-bot' 10 | exit 0 11 | 12 | else 13 | 14 | echo 'ERROR bestbuy-bot test Failed' 15 | exit 2 16 | 17 | fi -------------------------------------------------------------------------------- /scripts/test/bestbuy-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of bestbuy-find-listing test ' 3 | echo ' Should continuesly switch stores, check if the item is in-stock, then exit:0 ' 4 | 5 | USER_ENV=testUserInfo npm run bestbuy-bot 6 | echo ' Finished running bestbuy-bot' -------------------------------------------------------------------------------- /scripts/test/gamestop-bot.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of gamestop-bot test ' 3 | echo ' Should run a full cycle of gamestop-bot.js script, then exit: 0 ' 4 | 5 | USER_ENV=testUserInfo npm run gamestop-bot 6 | 7 | if [ $? -eq 0 ]; then 8 | 9 | echo 'Finished running gamestop-bot' 10 | 11 | else 12 | 13 | echo 'ERROR gamestop-bot test Failed' 14 | exit 2 15 | 16 | fi -------------------------------------------------------------------------------- /scripts/test/gamestop-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of gamestop-find-listing test ' 3 | echo ' Should continuesly switch stores, check if the item is in-stock, then exit:0 ' 4 | 5 | USER_ENV=testUserInfo npm run gamestop-bot 6 | echo ' Finished running gamestop-bot' -------------------------------------------------------------------------------- /scripts/test/micro-bot.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of micro-bot test ' 3 | echo ' Should run a full cycle of micro-bot.js script, then exit: 0 ' 4 | 5 | USER_ENV=testUserInfo npm run micro-bot 6 | 7 | if [ $? -eq 0 ]; then 8 | 9 | echo 'Finished running micro-bot' 10 | 11 | else 12 | 13 | echo 'ERROR micro-bot test Failed' 14 | exit 2 15 | 16 | fi -------------------------------------------------------------------------------- /scripts/test/micro-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of micro-find-listing test ' 3 | echo ' Should continuesly switch stores, check if the item is in-stock, then exit:0 ' 4 | 5 | USER_ENV=testUserInfo npm run micro-bot 6 | echo ' Finished running micro-bot' -------------------------------------------------------------------------------- /scripts/test/newegg-bot.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of newegg-bot test ' 3 | echo ' Should run a full cycle of newegg-bot.js script, then exit: 0 ' 4 | 5 | USER_ENV=testUserInfo npm run newegg-bot 6 | 7 | if [ $? -eq 0 ]; then 8 | 9 | echo 'Finished running newegg-bot' 10 | 11 | else 12 | 13 | echo 'ERROR newegg-bot test Failed' 14 | exit 2 15 | 16 | fi -------------------------------------------------------------------------------- /scripts/test/newegg-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of newegg-find-listing test ' 3 | echo ' Should continuesly switch stores, check if the item is in-stock, then exit:0 ' 4 | 5 | USER_ENV=testUserInfo npm run newegg-bot 6 | echo ' Finished running newegg-bot' -------------------------------------------------------------------------------- /scripts/test/target-bot.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of target-bot test ' 3 | echo ' Should run a full cycle of target-bot.js script, then exit: 0 ' 4 | 5 | USER_ENV=testUserInfo npm run target-bot 6 | 7 | if [ $? -eq 0 ]; then 8 | 9 | echo 'Finished running target-bot' 10 | 11 | else 12 | 13 | echo 'ERROR target-bot test Failed' 14 | exit 2 15 | 16 | fi -------------------------------------------------------------------------------- /scripts/test/target-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of target-find-listing test ' 3 | echo ' Should continuesly switch stores, check if the item is in-stock, then exit:0 ' 4 | 5 | USER_ENV=testUserInfo npm run target-bot 6 | echo ' Finished running target-bot' -------------------------------------------------------------------------------- /scripts/test/walmart-bot.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of walmart-bot test ' 3 | echo ' Should run a full cycle of walmart-bot.js script, then exit: 0 ' 4 | 5 | USER_ENV=testUserInfo npm run walmart-bot 6 | 7 | if [ $? -eq 0 ]; then 8 | 9 | echo 'Finished running walmart-bot' 10 | 11 | else 12 | 13 | echo 'ERROR walmart-bot test Failed' 14 | exit 2 15 | 16 | fi -------------------------------------------------------------------------------- /scripts/test/walmart-find-stocks.test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo ' Start of walmart-find-listing test ' 3 | echo ' Should continuesly switch stores, check if the item is in-stock, then exit:0 ' 4 | 5 | USER_ENV=testUserInfo npm run walmart-bot 6 | echo ' Finished running walmart-bot' -------------------------------------------------------------------------------- /scripts/walmart/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$USER_ENV" ] 4 | then 5 | export USER_ENV=userInfo 6 | else 7 | export USER_ENV=$USER_ENV 8 | fi 9 | echo "Environmnet: $USER_ENV\_environment" 10 | 11 | USER_ENV=$USER_ENV node scripts/walmart/walmart-bot.js -------------------------------------------------------------------------------- /scripts/walmart/myInfo.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config({ path: `scripts/walmart/user_info/.env.${process.env.USER_ENV}` }); 2 | var date = new Date(); 3 | var timeStamp = `${process.env.USER_ENV}_${date.getMonth()}-${date.getDay()}_${Math.floor(Math.random() * 100001)}`; 4 | let snapShotPath = 'record/screen_shots/walmart/' + `${timeStamp}`; 5 | 6 | let myemail; 7 | let mypassw; 8 | let mycvv; 9 | let listingURL; 10 | 11 | if (`${process.env.USER_ENV}` === 'testUserInfo') { 12 | myemail = process.env.TEST_USER_EMAIL; 13 | mypassw = process.env.TEST_USER_PASSW; 14 | mycvv = process.env.TEST_USER_CVV; 15 | listingURL = process.env.TEST_USER_LISTING_URL; 16 | } else { 17 | myemail = process.env.MY_EMAIL; 18 | mypassw = process.env.MY_PASSW; 19 | mycvv = process.env.MY_CVV; 20 | listingURL = process.env.LISTING_URL; 21 | } 22 | 23 | module.exports = { 24 | myemail, 25 | mypassw, 26 | mycvv, 27 | listingURL, 28 | snapShotPath, 29 | }; -------------------------------------------------------------------------------- /scripts/walmart/taskHandler.js: -------------------------------------------------------------------------------- 1 | const myInfo = require('./myInfo'); 2 | const utils = require('./utils'); 3 | const colors = require('colors'); 4 | 5 | async function logIn(page) { 6 | // LOGIN 7 | await page.waitForSelector(utils.selectors.get('account_selector')); 8 | await page.screenshot({ path: `${myInfo.snapShotPath}+start.png` }); 9 | 10 | await page.$eval(utils.selectors.get('account_selector'), (el) => el.click()); 11 | let list_items = await page.$eval( 12 | utils.selectors.get('account_information_selector'), 13 | (element) => { 14 | return element.innerText; 15 | } 16 | ); 17 | let needsLogIn = list_items.includes('Sign In'); 18 | 19 | // Navigate to login page 20 | while (needsLogIn) { 21 | console.log('Navigating to signin page ..'.yellow); 22 | await page.goto('https://www.walmart.com/account/login'); 23 | await page.waitForTimeout(700); // Avoid network slowdown 24 | 25 | // Enter login credentials & signin 26 | console.log('Signing in ..'.yellow); 27 | 28 | //email 29 | await page.waitForSelector(utils.selectors.get('email_selector')); 30 | await page.$eval(utils.selectors.get('email_selector'), (el) => el.click()); 31 | await page.type(utils.selectors.get('email_selector'), myInfo.myemail, {delay: 50}); 32 | 33 | //password 34 | await page.$eval(utils.selectors.get('password_selector'), (el) => 35 | el.click() 36 | ); 37 | await page.type(utils.selectors.get('password_selector'), myInfo.mypassw, {delay: 50}); 38 | 39 | //submit 40 | await page.focus(utils.selectors.get('singin_selector')); 41 | await page.keyboard.press('Enter'); 42 | await page.screenshot({ path: `${myInfo.snapShotPath}+login_attempt.png` }); 43 | await page.waitForTimeout(4000); // Time to load account username 44 | 45 | await page.goto('https://www.walmart.com', { waitUntil: "networkidle2" }); 46 | 47 | await page.$eval(utils.selectors.get('account_selector'), (el) => el.click()); 48 | list_items = await page.$eval( 49 | utils.selectors.get('account_information_selector'), 50 | (element) => { 51 | return element.innerText; 52 | } 53 | ); 54 | needsLogIn = list_items.includes('Sign In'); 55 | } 56 | console.log('Signed in succesfully ..'.yellow); 57 | } 58 | 59 | async function checkoutCart(page) { 60 | await page.focus(utils.selectors.get('chekout_bttn_selector_1')); 61 | await page.keyboard.press('Enter'); 62 | await page.waitForTimeout(1000); 63 | 64 | // Delivery vs Pickup 65 | await page.screenshot({path: `${myInfo.snapShotPath}+checkout_delivery.png`}); 66 | await page.waitForSelector(utils.selectors.get('chekout_bttn_selector_2')); 67 | await page.focus(utils.selectors.get('chekout_bttn_selector_2')); 68 | await page.keyboard.press('Enter'); 69 | 70 | // Confirm Address 71 | await page.screenshot({path: `${myInfo.snapShotPath}+checkout_address.png`}); 72 | await page.waitForSelector(utils.selectors.get('chekout_bttn_selector_3')); 73 | await page.focus(utils.selectors.get('chekout_bttn_selector_3')); 74 | await page.keyboard.press('Enter'); 75 | 76 | // Input credit-card cvv 77 | await page.waitForSelector(utils.selectors.get('review_bttn_selector')); 78 | if (await page.$(utils.selectors.get('cvv_input_selector')) !== null){ 79 | await page.focus(utils.selectors.get('cvv_input_selector')); 80 | await page.keyboard.press('Enter'); 81 | await page.type(utils.selectors.get('cvv_input_selector'), myInfo.mycvv); 82 | 83 | await page.focus(utils.selectors.get('review_bttn_selector')); 84 | await page.keyboard.press('Enter'); 85 | await page.screenshot({ path: `${myInfo.snapShotPath}+cvv_added.png` }); 86 | } 87 | 88 | //Moment of truth.. 89 | await page.waitForSelector(utils.selectors.get('place_order_bttn_selector')); 90 | await page.focus(utils.selectors.get('place_order_bttn_selector')); 91 | //SKIP IF RUNNING TEST 92 | if (`${process.env.USER_ENV}` == "userInfo" ) { 93 | await page.keyboard.press('Enter'); 94 | } 95 | await page.waitForTimeout(7000); 96 | await page.screenshot({ path: `${myInfo.snapShotPath}+result_page.png` }); 97 | } 98 | 99 | module.exports = { 100 | logIn, 101 | checkoutCart, 102 | }; 103 | -------------------------------------------------------------------------------- /scripts/walmart/user_info/.env.userInfo: -------------------------------------------------------------------------------- 1 | #enter email 2 | MY_EMAIL= 3 | 4 | #enter password 5 | MY_PASSW= 6 | 7 | #enter payment card cvv 8 | MY_CVV= 9 | 10 | #enter listing url 11 | LISTING_URL= -------------------------------------------------------------------------------- /scripts/walmart/utils.js: -------------------------------------------------------------------------------- 1 | let selectors = new Map(); 2 | selectors.set('account_selector', '#hf-account-flyout > span > span > span.b_a.ab_b.b_g.b_b.b_p.x_a.x_h.x_i'); 3 | selectors.set('account_information_selector', '#vh-account-menu-root > div.p_a.p_o'); 4 | selectors.set('email_selector', '#email'); 5 | selectors.set('password_selector', '#password'); 6 | selectors.set('singin_selector', '#sign-in-form > button.button.m-margin-top.text-inherit'); 7 | selectors.set('sold_out_selector', '#blitzitem-container'); 8 | selectors.set('add_cart_bttn_selector', '#add-on-atc-container > div:nth-child(1) > section > div.valign-middle.display-inline-block.prod-product-primary-cta.primaryProductCTA-marker > div.prod-product-cta-add-to-cart.display-inline-block > button > span'); 9 | selectors.set('chekout_bttn_selector_1', '#cart-root-container-content-skip > div > div > div.text-left.Grid > div.Grid-col.u-size-1.u-size-3-12-m.u-size-3-12-l > div > div > div.cart-pos-main-actions.s-margin-top.cart-pos-checkout-button > div > div > button.button.ios-primary-btn-touch-fix.hide-content-max-m.checkoutBtn.button--primary'); 10 | selectors.set('chekout_bttn_selector_2', 'body > div.js-content > div > div.checkout-wrapper > div > div.accordion-inner-wrapper > div.checkout-accordion > div > div > div > div:nth-child(1) > div > div.CXO_module_body.ResponsiveContainer > div > div > div > div.text-left.Grid > div > div > div.CXO_fulfillment_continue > button'); 11 | selectors.set('chekout_bttn_selector_3', 'body > div.js-content > div > div.checkout-wrapper > div > div.accordion-inner-wrapper > div.checkout-accordion > div > div > div > div:nth-child(2) > div.CXO_module_container > div.CXO_module_body.ResponsiveContainer > div > div > div > div.text-left.Grid > div > div > div > div > div.arrange > div.arrange-fill.u-size-1-12-m > button'); 12 | selectors.set('cvv_panel_selector', 'body > div.js-content > div > div.checkout-wrapper > div > div.accordion-inner-wrapper > div.checkout-accordion > div > div > div > div:nth-child(3) > div.CXO_module_container > div.CXO_module_body.ResponsiveContainer > div > div > div > div.text-left.Grid > div:nth-child(2) > div > div > div > div.text-left.Grid > div:nth-child(1) > div > div > div > div > div:nth-child(2) > div > div.card-body.clearfix'); 13 | selectors.set('cvv_input_selector', '#cvv-confirm'); 14 | selectors.set('review_bttn_selector', 'body > div.js-content > div > div.checkout-wrapper > div > div.accordion-inner-wrapper > div.checkout-accordion > div > div > div > div:nth-child(3) > div.CXO_module_container > div.CXO_module_body.ResponsiveContainer > div > div > div > div.text-left.Grid > div:nth-child(2) > div > button'); 15 | selectors.set('place_order_bttn_selector', 'body > div.js-content > div > div.checkout-wrapper > div > div.accordion-inner-wrapper > div.checkout-accordion > div > div > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div > div > div.Grid-col.u-size-1.u-size-3-12-s.u-size-3-12-m > div > form > div > button'); 16 | 17 | module.exports = { 18 | selectors, 19 | } -------------------------------------------------------------------------------- /scripts/walmart/walmart-bot.js: -------------------------------------------------------------------------------- 1 | const utils = require("./utils"); 2 | const myInfo = require("./myInfo"); 3 | const taskHandler = require("./taskHandler"); 4 | const Spinner = require("cli-spinner"); 5 | const puppeteer = require("puppeteer"); 6 | const colors = require("colors"); 7 | 8 | async function addToCart(page) { 9 | await page.waitForSelector(utils.selectors.get("add_cart_bttn_selector")); 10 | await page.$eval(utils.selectors.get("add_cart_bttn_selector"), (el) => el.click()); 11 | console.log("Item added to cart .."); 12 | 13 | await page.waitForTimeout(2000); 14 | await page.screenshot({ path: `${myInfo.snapShotPath}+added_to_cart.png` }); 15 | } 16 | 17 | async function walmartBot() { 18 | // Spinner 19 | var mySpinner = new Spinner.Spinner("processing.. %s"); 20 | mySpinner.setSpinnerString("|/-\\"); 21 | mySpinner.start(); 22 | 23 | try { 24 | 25 | let launcherArgs; 26 | let pathToBrowser; 27 | if (process.env.USER_ENV === 'testUserInfo') { 28 | launcherArgs = ['--no-sandbox', '--deterministic-fetch', '--disable-setuid-sandbox', `--window-size=1025,1025`]; 29 | pathToBrowser = process.env.PUPPETEER_EXEC_PATH; 30 | } else { 31 | launcherArgs = ['--no-sandbox', `--window-size=1025,1025`]; 32 | } 33 | 34 | // Start of test: Launch and go to login website 35 | const browser = await puppeteer.launch({ 36 | defaultViewport: null, 37 | headless: false, // not sure about running headless.. Bot detection. 38 | args: launcherArgs, 39 | executablePath: pathToBrowser, 40 | }); 41 | 42 | const page = await browser.newPage(); 43 | await page.setDefaultNavigationTimeout(0); 44 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 45 | await page.goto("https://www.walmart.com", { waitUntil: "networkidle2" }); 46 | await taskHandler.logIn(page); 47 | 48 | // TESTING - Comment out when done. 49 | // For cleaning up account/pause program - usefull for test setup 50 | // await page.waitForTimeout(9000000); 51 | 52 | // Navigate to Sony PS5 listing & add to cart 53 | let amountOrdered = 0; 54 | while (amountOrdered < 1) { 55 | 56 | console.log("\n[1/4] .. Navigating to listing page ..".bgBlue); 57 | console.log(`Url: ${myInfo.listingURL}`.yellow); 58 | 59 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 60 | await page.goto(`${myInfo.listingURL}`, { waitUntil: "networkidle2" }); 61 | await page.screenshot({ path: `${myInfo.snapShotPath}+listing_page.png` }); 62 | 63 | // Checking to see if listing is out of stock 64 | let isOutOfStock; 65 | let testRuns; 66 | 67 | if (await page.$(utils.selectors.get('sold_out_selector')) !== null) { 68 | isOutOfStock = true; 69 | } 70 | 71 | while (isOutOfStock) { 72 | console.log('\nOUT OF STOCK'.red); 73 | console.log('\nRefreshing Page..'.yellow); 74 | await page.reload(); 75 | 76 | await page.waitForSelector('#product-overview > div > div:nth-child(3) > div > h1'); 77 | await page.screenshot({ path: `${myInfo.snapShotPath}+listing_page.png` }); 78 | 79 | if (await page.$(utils.selectors.get('sold_out_selector')) !== null) { 80 | isOutOfStock = true; 81 | } 82 | 83 | //EXIT IF RUNNING TEST 84 | if ((`${process.env.USER_ENV}` == "testUserInfo" && testRuns == 5)) { 85 | return; 86 | } 87 | testRuns++; 88 | } 89 | console.log("\nListing is in stock !!".bgBlue); 90 | 91 | // Add listing to cart 92 | console.log("\n[2/4] .. Adding item to cart ..".bgBlue); 93 | await addToCart(page); 94 | 95 | // Navigate to cart 96 | console.log("\n[3/4] .. Navigating to cart ..".bgBlue); 97 | const cartURL = "https://www.walmart.com/cart"; 98 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 99 | await page.goto(`${cartURL}`, { waitUntil: "networkidle2" }); 100 | await page.screenshot({ path: `${myInfo.snapShotPath}+nav_to_cart.png` }); 101 | 102 | //Checkout listing 103 | console.log("\n[4/4] .. Checking out cart ..".bgBlue); 104 | await taskHandler.checkoutCart(page); 105 | 106 | // Ctrl+C && Celebrate 107 | console.log("\nDone. Goteee boiiis!!! \n".rainbow); 108 | console.log("\nLook at account purchase history to verify \n".bgRed); 109 | 110 | // Done 111 | await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'); 112 | await page.goto( 113 | "https://www.tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254", 114 | { waitUntil: "networkidle2" } 115 | ); 116 | amountOrdered++; 117 | } 118 | await page.waitForTimeout(7000); 119 | await page.close(); 120 | await browser.close(); 121 | await mySpinner.stop(); 122 | await process.exit(); 123 | return; 124 | } 125 | catch (error) { 126 | // expected output: ReferenceError: nonExistentFunction is not defined 127 | // Note - error messages will vary depending on browser 128 | console.log("\n" + error); 129 | throw error; 130 | } 131 | finally { 132 | 133 | } 134 | } 135 | 136 | walmartBot(); 137 | -------------------------------------------------------------------------------- /youtube-example.js: -------------------------------------------------------------------------------- 1 | const myemail = ''; // Enter email. ex - const myemail = 'myEmail@email.com'; 2 | const mypassw = ''; // Enter password. ex - const mypassw = 'password'; 3 | 4 | const { time } = require("console"); 5 | const puppeteer = require("puppeteer"); 6 | var date = new Date(); 7 | var timeStamp = date.getTime(); 8 | let snapShotPath = // ex, '/Users/me/Documents//record/screen_shots/' 9 | '../../record/screen_shots/' + 10 | `${timeStamp}` + 11 | ".png"; 12 | 13 | let singin_selector_1 = '#button.style-scope.ytd-button-renderer.style-suggestive.size-small'; 14 | let singin_selector_2 = 'button.VfPpkd-LgbsSe.VfPpkd-LgbsSe-OWXEXe-k8QpJ.VfPpkd-LgbsSe-OWXEXe-dgl2Hf.nCP5yc.AjY5Oe.DuMIQc.qIypjc.TrZEUc'; 15 | let singin_selector_3 = 'button.VfPpkd-LgbsSe.VfPpkd-LgbsSe-OWXEXe-k8QpJ.VfPpkd-LgbsSe-OWXEXe-dgl2Hf.nCP5yc.AjY5Oe.DuMIQc.qIypjc.TrZEUc'; 16 | const email_selector = 'input#identifierId.whsOnd.zHQkBf'; 17 | const password_selector = 'input.whsOnd.zHQkBf'; 18 | 19 | (async () => { 20 | // Start of test: Launch and go to login website 21 | const browser = await puppeteer.launch({ 22 | headless: false, 23 | defaultViewport: null, 24 | args: ['--disable-setuid-sandbox', '--no-sandbox', `--window-size=1025,1025`], 25 | //executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', 26 | }); 27 | const page = await browser.newPage(); 28 | await page.goto('https://www.youtube.com', { waitUntil: "networkidle2" }); 29 | 30 | const html = await page.evaluate(() => document.body.innerHTML); 31 | await page.screenshot({ path: snapShotPath }); 32 | 33 | // LOGIN 34 | // Navigate to login page 35 | await page.$eval(singin_selector_1, (el) => el.click()); 36 | await page.waitForNavigation({ waitUntil: 'domcontentloaded' }); 37 | await page.screenshot({ path: snapShotPath }); 38 | 39 | // Enter login credentials & signin 40 | // Email 41 | await page.$eval(email_selector, (el) => el.click()); 42 | await page.type(email_selector, myemail, {delay: 30}); 43 | await page.$eval(singin_selector_2, (el) => el.click()); 44 | await page.waitForNavigation({ waitUntil: 'domcontentloaded' }); 45 | await page.screenshot({ path: snapShotPath }); 46 | 47 | //Password 48 | await page.$eval(password_selector, (el) => el.click()); 49 | await page.waitForTimeout(700); 50 | await page.type(password_selector, mypassw, {delay: 30}); 51 | await page.$eval(singin_selector_3, (el) => el.click()); 52 | await page.waitForNavigation({ waitUntil: 'domcontentloaded' }); 53 | await page.screenshot({ path: snapShotPath }); 54 | 55 | await browser.close(); 56 | })(); 57 | --------------------------------------------------------------------------------