Skip to content

Commit

Permalink
feat(store): specify links to navigate to between product searches (#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
neatchee authored Jan 17, 2021
1 parent 2120d29 commit 0982774
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
73 changes: 73 additions & 0 deletions src/store/lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ async function lookup(browser: Browser, store: Store) {
} catch {}
});

if (store.captchaDeterrent) {
await runCaptchaDeterrent(browser, store, page);
}

let statusCode = 0;

try {
Expand Down Expand Up @@ -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(
Expand Down
10 changes: 10 additions & 0 deletions src/store/model/amazon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
11 changes: 11 additions & 0 deletions src/store/model/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type Pricing = {

export type Brand =
| 'test:brand'
| 'captcha-deterrent'
| 'amd'
| 'asrock'
| 'asus'
Expand All @@ -37,6 +38,7 @@ export type Brand =

export type Series =
| 'test:series'
| 'captcha-deterrent'
| '3060ti'
| '3070'
| '3080'
Expand All @@ -57,6 +59,7 @@ export type Series =

export type Model =
| 'test:model'
| 'captcha-deterrent'
| '5600x'
| '5800x'
| '5900x'
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -215,4 +224,6 @@ export type Store = {

proxyList?: string[];
currentProxyIndex?: number;

captchaDeterrent?: CaptchaDeterrent;
};

0 comments on commit 0982774

Please sign in to comment.