Skip to content

Commit 5698709

Browse files
committed
Add ability to open product url automatically
1 parent 1cbbc43 commit 5698709

File tree

10 files changed

+142
-77
lines changed

10 files changed

+142
-77
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Buy me a [pizza](buymeacoff.ee/PrinceSingh) if you'd like to see this project ex
66
<br><br>
77
> How does it work?
88
9-
Enter the product URLs and set how often you want the program to check if those products are in stock. When an item becomes available, it will notify you through both text on console and three auditory beeps.
9+
Enter the product URLs, set how often you want the program to check if those products are in stock, and if you want the product page to normal automatically in your default web browser when it gets in stock. When an item becomes available, it will notify you through both text on console and three auditory beeps.
1010

1111
> What stores/wesbites are supported?
1212
@@ -48,4 +48,5 @@ Currently, the following stores are supported:
4848
* Add color to console
4949
* ~~Initially create seperation between intervals for Amazon items~~
5050
* ~~Add a way to have independent delay timers for Amazon~~
51+
* ~~Open product page when in stock~~
5152
* ~~Fix~~ Find Bugs

main.js

Lines changed: 85 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { fileURLToPath } from "url";
12
import antonline from './stores/antonline.js'
23
import amazon from './stores/amazon.js'
34
import bestbuy from './stores/bestbuy.js'
@@ -15,7 +16,7 @@ const URLS = [
1516
"https://www.bestbuy.com/site/amd-ryzen-9-5900x-4th-gen-12-core-24-threads-unlocked-desktop-processor-without-cooler/6438942.p?skuId=6438942",
1617
"https://www.bestbuy.com/site/sony-playstation-5-console/6426149.p?skuId=6426149",
1718
"https://www.costco.com/sony-playstation-5-gaming-console-bundle.product.100691489.html",
18-
"https://www.microcenter.com/product/630283/Ryzen_9_5900X_Vermeer_37GHz_12-Core_AM4_Boxed_Processor",
19+
// "https://www.microcenter.com/product/630283/Ryzen_9_5900X_Vermeer_37GHz_12-Core_AM4_Boxed_Processor",
1920
"https://www.newegg.com/amd-ryzen-9-5900x/p/N82E16819113664?Item=N82E16819113664",
2021
"https://www.newegg.com/asus-geforce-rtx-3080-rog-strix-rtx3080-o10g-gaming/p/N82E16814126457",
2122
"https://www.newegg.com/asus-geforce-rtx-3080-tuf-rtx3080-o10g-gaming/p/N82E16814126452",
@@ -29,10 +30,18 @@ const INTERVAL = {
2930
value: 10
3031
}
3132

33+
// Opens the product url in the default browser if set to true
34+
export const OPEN_URL = true;
35+
3236
// Separates the check between Amazon items by this value
3337
const AMAZON_DELAY = 25;
3438

3539

40+
// Runs main only if this file is executed
41+
if (process.argv[1] === fileURLToPath(import.meta.url))
42+
main();
43+
44+
3645
// https://www.XXX.com/... -> XXX
3746
function getDomainName(url) {
3847
let hostName = new URL(url).hostname;
@@ -65,18 +74,24 @@ async function checkStoreWithDelay(item) {
6574
let timer = (firstRun) => {
6675
return new Promise(
6776
function(resolve) {
68-
item.storeFunc(item.url, item.interval, INTERVAL.value, firstRun, resolve);
77+
item.storeFunc(item.url, item.interval, INTERVAL.value, firstRun, item.urlOpened, resolve);
6978
}
7079
);
7180
}
7281

7382
timer(item.firstRun).then(
74-
async function(interval) {
83+
async function({interval, urlOpened}) {
7584
if (item.interval.value != interval) {
7685
item.firstRun = true;
7786
item.interval.value = interval;
7887
} else item.firstRun = false;
7988

89+
if (OPEN_URL && urlOpened && urlOpened != item.urlOpened) {
90+
item.urlOpened = true;
91+
setTimeout(() => item.urlOpened = false, 1000 * 115) // Open URL every 2 minutes
92+
}
93+
94+
8095
switch(item.interval.unit) {
8196
case 'seconds':
8297
await setTimeout(checkStoreWithDelay, item.interval.value * 1000, item)
@@ -95,68 +110,70 @@ async function checkStoreWithDelay(item) {
95110
}
96111

97112

98-
let amazonItems = [];
99-
function amazonItem(url) {
100-
this.url = url;
101-
this.interval = {...INTERVAL};
102-
this.firstRun = true;
103-
this.storeFunc = amazon;
104-
};
105-
106-
107-
URLS.forEach(url => {
108-
let storeName;
109-
try {
110-
storeName = getDomainName(url);
111-
} catch(e) {
112-
console.error('Incorrect URL format:', url)
113-
console.error(e)
114-
}
115-
116-
switch(storeName) {
117-
case 'antonline':
118-
checkStore(antonline, url);
119-
break;
120-
121-
case 'amazon':
122-
amazonItems.push(new amazonItem(url));
123-
break;
124-
125-
case 'bestbuy':
126-
checkStore(bestbuy, url);
127-
break;
128-
129-
case 'costco':
130-
checkStore(costco, url);
131-
break;
132-
133-
case 'microcenter':
134-
checkStore(microcenter, url);
135-
break;
136-
137-
case 'newegg':
138-
checkStore(newegg, url);
139-
break;
140-
141-
default:
142-
console.error('This store is not supported:', storeName)
143-
}
144-
});
145-
146-
if (amazonItems.length > 0)
147-
amazonItems.forEach(
148-
(item, idx) => {
149-
switch(INTERVAL.unit) {
150-
case 'seconds':
151-
setTimeout(checkStoreWithDelay, AMAZON_DELAY * 1000 * idx, item);
152-
break;
153-
154-
case 'minutes':
155-
setTimeout(checkStoreWithDelay, AMAZON_DELAY * 1000 * 60 * idx, item);
156-
break;
157-
158-
case 'hours':
159-
setTimeout(checkStoreWithDelay, AMAZON_DELAY * 1000 * 60 * 60 * idx, item);
160-
break;
161-
}
162-
});
113+
function main() {
114+
let amazonItems = [];
115+
function amazonItem(url) {
116+
this.url = url;
117+
this.interval = {...INTERVAL};
118+
this.firstRun = true;
119+
this.urlOpened = false;
120+
this.storeFunc = amazon;
121+
};
122+
123+
URLS.forEach(url => {
124+
let storeName;
125+
try {
126+
storeName = getDomainName(url);
127+
} catch(e) {
128+
console.error('Incorrect URL format:', url)
129+
console.error(e)
130+
}
131+
132+
switch(storeName) {
133+
case 'antonline':
134+
checkStore(antonline, url);
135+
break;
136+
137+
case 'amazon':
138+
amazonItems.push(new amazonItem(url));
139+
break;
140+
141+
case 'bestbuy':
142+
checkStore(bestbuy, url);
143+
break;
144+
145+
case 'costco':
146+
checkStore(costco, url);
147+
break;
148+
149+
case 'microcenter':
150+
checkStore(microcenter, url);
151+
break;
152+
153+
case 'newegg':
154+
checkStore(newegg, url);
155+
break;
156+
157+
default:
158+
console.error('This store is not supported:', storeName)
159+
}
160+
});
161+
162+
if (amazonItems.length > 0)
163+
amazonItems.forEach(
164+
(item, idx) => {
165+
switch(INTERVAL.unit) {
166+
case 'seconds':
167+
setTimeout(checkStoreWithDelay, AMAZON_DELAY * 1000 * idx, item);
168+
break;
169+
170+
case 'minutes':
171+
setTimeout(checkStoreWithDelay, AMAZON_DELAY * 1000 * 60 * idx, item);
172+
break;
173+
174+
case 'hours':
175+
setTimeout(checkStoreWithDelay, AMAZON_DELAY * 1000 * 60 * 60 * idx, item);
176+
break;
177+
}
178+
});
179+
}

package-lock.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"axios": "^0.21.0",
55
"beepbeep": "^1.3.0",
66
"dom-parser": "^0.1.6",
7-
"moment": "^2.29.1"
7+
"moment": "^2.29.1",
8+
"open": "^7.3.0"
89
}
910
}

stores/amazon.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { fileURLToPath } from "url";
2+
import { OPEN_URL } from '../main.js'
23
import fs from "fs";
34
import threeBeeps from "../beep.js"
45
import axios from "axios";
56
import moment from "moment";
67
import DomParser from "dom-parser"; // https://www.npmjs.com/package/dom-parser
8+
import open from "open"
79

810

911
if (process.argv[1] === fileURLToPath(import.meta.url)) {
@@ -12,7 +14,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
1214
value: 25 // Amazon detects bots if too low, do > 10 seconds
1315
}
1416
let url = 'https://www.amazon.com/Coredy-Super-Strong-Automatic-Self-Charging-Medium-Pile/dp/B07NPNN57S'
15-
amazon(url, interval);
17+
amazon(url, interval, interval.value, true, false, () => null);
1618
}
1719

1820

@@ -24,7 +26,7 @@ function writeErrorToFile(error) {
2426
}
2527

2628

27-
export default async function amazon(url, interval, originalIntervalValue, firstRun, resolve) {
29+
export default async function amazon(url, interval, originalIntervalValue, firstRun, urlOpened, resolve) {
2830
try {
2931
let res = await axios.get(url, {
3032
headers: {
@@ -47,12 +49,13 @@ export default async function amazon(url, interval, originalIntervalValue, first
4749
}
4850
else if (inventory != null && inventory == 'Add to Cart') {
4951
threeBeeps();
52+
if (OPEN_URL && !urlOpened) { open(url); urlOpened = true; }
5053
console.info(moment().format('LTS') + ': ***** In Stock at Amazon *****: ', title);
5154
console.info(url);
5255
}
53-
resolve(interval.value);
56+
resolve({interval: interval.value, urlOpened: urlOpened});
5457
}
55-
else resolve(Math.floor(interval.value + Math.random() * originalIntervalValue))
58+
else resolve({interval: Math.floor(interval.value + Math.random() * originalIntervalValue), urlOpened: urlOpened})
5659

5760
} catch (e) {
5861
writeErrorToFile(e)

stores/antonline.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import { fileURLToPath } from "url";
2+
import { OPEN_URL } from '../main.js'
23
import fs from "fs";
34
import threeBeeps from "../beep.js"
45
import axios from "axios";
56
import moment from "moment";
67
import DomParser from "dom-parser"; // https://www.npmjs.com/package/dom-parser
8+
import open from "open"
79

810

911
if (process.argv[1] === fileURLToPath(import.meta.url)) {
1012
let interval = {
1113
unit: 'seconds', // seconds, m: minutes, h: hours
12-
value: 5
14+
value: 30
1315
}
14-
let url = 'https://www.antonline.com/Sony/Electronics/Gaming_Devices/Gaming_Consoles/1413553'
16+
let url = 'https://www.antonline.com/Sony/Electronics/Audio_Electronics/Headsets+Earsets/1398728'
1517
antonline(url, interval);
1618
}
1719

1820

1921
let firstRun = new Set();
22+
let urlOpened = false;
2023
export default async function antonline(url, interval) {
2124
try {
2225
var res = await axios.get(url);
@@ -33,6 +36,7 @@ export default async function antonline(url, interval) {
3336
}
3437
else if (inventory && inventory == 'Add to Cart') {
3538
threeBeeps();
39+
if (OPEN_URL && !urlOpened) { open(url); urlOpened = true; setTimeout(() => urlOpened = false, 1000 * 115) } // Open URL every 2 minutes
3640
console.info(moment().format('LTS') + ': ***** In Stock at AntOnline *****: ', title);
3741
console.info(url);
3842
}

stores/bestbuy.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { fileURLToPath } from "url";
2+
import { OPEN_URL } from '../main.js'
23
import fs from 'fs';
34
import threeBeeps from "../beep.js"
45
import axios from "axios";
56
import moment from "moment";
67
import DomParser from "dom-parser"; // https://www.npmjs.com/package/dom-parser
8+
import open from "open"
79

810

911
if (process.argv[1] === fileURLToPath(import.meta.url)) {
@@ -17,6 +19,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
1719

1820

1921
let firstRun = new Set();
22+
let urlOpened = false;
2023
export default async function bestbuy(url, interval) {
2124
try {
2225
var res = await axios.get(url);
@@ -30,11 +33,13 @@ export default async function bestbuy(url, interval) {
3033
if (inventory.length > 0) inventory = inventory[0].textContent
3134
if (open_box && open_box.length > 0) {
3235
threeBeeps();
36+
if (OPEN_URL && !urlOpened) { open(url); urlOpened = true; setTimeout(() => urlOpened = false, 1000 * 115) } // Open URL every 2 minutes
3337
console.info(moment().format('LTS') + ': ***** Open Box at BestBuy *****: ', title);
3438
console.info(url);
3539
}
3640
if (inventory == 'Add to Cart') {
3741
threeBeeps();
42+
if (OPEN_URL && !urlOpened) { open(url); urlOpened = true; setTimeout(() => urlOpened = false, 1000 * 115) } // Open URL every 2 minutes
3843
console.info(moment().format('LTS') + ': ***** In Stock at BestBuy *****: ', title);
3944
console.info(url);
4045
}

stores/costco.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { fileURLToPath } from "url";
2+
import { OPEN_URL } from '../main.js'
23
import fs from "fs";
34
import threeBeeps from "../beep.js"
45
import axios from "axios";
56
import moment from "moment";
67
import DomParser from "dom-parser"; // https://www.npmjs.com/package/dom-parser
8+
import open from "open"
79

810

911
if (process.argv[1] === fileURLToPath(import.meta.url)) {
@@ -17,6 +19,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
1719

1820

1921
let firstRun = new Set();
22+
let urlOpened = false;
2023
export default async function costco(url, interval) {
2124
try {
2225
var res = await axios.get(url);
@@ -32,6 +35,7 @@ export default async function costco(url, interval) {
3235
}
3336
else if (inventory != 'Out of Stock') {
3437
threeBeeps();
38+
if (OPEN_URL && !urlOpened) { open(url); urlOpened = true; setTimeout(() => urlOpened = false, 1000 * 115) } // Open URL every 2 minutes
3539
console.info(moment().format('LTS') + ': ***** In Stock at Costco *****: ', title);
3640
console.info(url);
3741
}

0 commit comments

Comments
 (0)