feat(store): specify links to navigate to between product searches (#1542)

Fixes #1504

When querying a store, if `deterrentLinks` has been defined, pick one at random and navigate there then wait 3 seconds. This should help reduce the likelihood of being sent to a captcha on subsequent page loads from the same store.
This commit is contained in:
neatchee
2021-01-17 05:27:08 -08:00
committed by GitHub
parent 2120d2901d
commit 09827741ae
4 changed files with 96 additions and 0 deletions
+2
View File
@@ -197,6 +197,7 @@ const notifications = {
3070: envOrArray(process.env.DISCORD_NOTIFY_GROUP_3070),
3080: envOrArray(process.env.DISCORD_NOTIFY_GROUP_3080),
3090: envOrArray(process.env.DISCORD_NOTIFY_GROUP_3090),
'captcha-deterrent': [],
darkhero: envOrArray(process.env.DISCORD_NOTIFY_GROUP_DARKHERO),
rx6800: envOrArray(process.env.DISCORD_NOTIFY_GROUP_RX6800),
rx6800xt: envOrArray(process.env.DISCORD_NOTIFY_GROUP_RX6800XT),
@@ -348,6 +349,7 @@ const store = {
3070: envOrNumber(process.env.MAX_PRICE_SERIES_3070),
3080: envOrNumber(process.env.MAX_PRICE_SERIES_3080),
3090: envOrNumber(process.env.MAX_PRICE_SERIES_3090),
'captcha-deterrent': 0,
darkhero: envOrNumber(process.env.MAX_PRICE_SERIES_DARKHERO),
rx6800: envOrNumber(process.env.MAX_PRICE_SERIES_RX6800),
rx6800xt: envOrNumber(process.env.MAX_PRICE_SERIES_RX6800XT),
+73
View File
@@ -234,6 +234,10 @@ async function lookup(browser: Browser, store: Store) {
} catch {}
});
if (store.captchaDeterrent) {
await runCaptchaDeterrent(browser, store, page);
}
let statusCode = 0;
try {
@@ -477,6 +481,75 @@ async function lookupCardInStock(store: Store, page: Page, link: Link) {
return true;
}
async function runCaptchaDeterrent(browser: Browser, store: Store, page: Page) {
const successStatusCodes = store.successStatusCodes ?? [[0, 399]];
let statusCode = 0;
let deterrentLinks: string[] = [];
logger.debug(`[${store.name}] Navigating to random anti-captcha page...`);
if (store.captchaDeterrent?.hardLinks?.length) {
deterrentLinks = deterrentLinks.concat(
store.captchaDeterrent.hardLinks
);
}
if (store.captchaDeterrent?.searchUrl) {
if (store.captchaDeterrent.searchTerms) {
store.captchaDeterrent.searchTerms.forEach((element) =>
deterrentLinks.push(
store.captchaDeterrent?.searchUrl
? store.captchaDeterrent.searchUrl.replace(
'%%s',
element
)
: ''
)
);
}
}
if (deterrentLinks.length > 0) {
const link: Link = {
brand: 'captcha-deterrent',
model: 'captcha-deterrent',
series: 'captcha-deterrent',
url:
deterrentLinks[
Math.floor(Math.random() * deterrentLinks.length)
]
};
logger.debug(`Selected captcha-deterrent link: ${link.url}`);
try {
const givenWaitFor = store.waitUntil
? store.waitUntil
: 'networkidle0';
const response: Response | null = await page.goto(link.url, {
waitUntil: givenWaitFor
});
statusCode = await handleResponse(
browser,
store,
page,
link,
response
);
setTimeout(() => {
// Do nothing
}, 3000);
} catch (error: unknown) {
logger.error(error);
}
if (!isStatusCodeInRange(statusCode, successStatusCodes)) {
logger.warn(
`✖ [${store.name}] - Failed to navigate to anti-captcha target: ${link.url}`
);
}
}
}
export async function tryLookupAndLoop(browser: Browser, store: Store) {
if (!browser.isConnected()) {
logger.debug(
+10
View File
@@ -2,6 +2,16 @@ import {Store} from './store';
export const Amazon: Store = {
backoffStatusCodes: [403, 429, 503],
captchaDeterrent: {
hardLinks: [
'https://www.amazon.com/Amazon-Video/b/?ie=UTF8&node=2858778011&ref_=nav_cs_prime_video',
'https://www.amazon.com/alm/storefront?almBrandId=VUZHIFdob2xlIEZvb2Rz&ref_=nav_cs_whole_foods_in_region',
'https://www.amazon.com/gp/goldbox?ref_=nav_cs_gb'
],
searchTerms: ['goober', 'dungeons+and+dragons'],
searchUrl:
'https://www.amazon.com/s?k=%%s&i=todays-deals&ref=nb_sb_noss_2'
},
currency: '$',
labels: {
captcha: {
+11
View File
@@ -12,6 +12,7 @@ export type Pricing = {
export type Brand =
| 'test:brand'
| 'captcha-deterrent'
| 'amd'
| 'asrock'
| 'asus'
@@ -37,6 +38,7 @@ export type Brand =
export type Series =
| 'test:series'
| 'captcha-deterrent'
| '3060ti'
| '3070'
| '3080'
@@ -57,6 +59,7 @@ export type Series =
export type Model =
| 'test:model'
| 'captcha-deterrent'
| '5600x'
| '5800x'
| '5900x'
@@ -181,6 +184,12 @@ export type Labels = {
maxPrice?: Pricing;
};
export type CaptchaDeterrent = {
hardLinks?: string[];
searchUrl?: string;
searchTerms?: string[];
};
export type StatusCodeRangeArray = Array<number | [number, number]>;
export type Store = {
@@ -215,4 +224,6 @@ export type Store = {
proxyList?: string[];
currentProxyIndex?: number;
captchaDeterrent?: CaptchaDeterrent;
};