Skip to content

Instantly share code, notes, and snippets.

@anchetaWern
Created March 25, 2025 06:22
Show Gist options
  • Save anchetaWern/2d5220d557c08a55b12bbd599bd19125 to your computer and use it in GitHub Desktop.
Save anchetaWern/2d5220d557c08a55b12bbd599bd19125 to your computer and use it in GitHub Desktop.
profitl seller stock fix
import React, { useRef, useEffect, useState } from "react";
import { View, StyleSheet } from "react-native";
import { WebView } from "react-native-webview";
import AlertBox from './AlertBox';
import LabelText from './LabelText';
const injectScript = `
const timeout = 1000 * 180;
async function getAmazonSellerStockData(scrapedASIN) {
const inventory = [];
const amazonRootElement = document.getElementById("qid");
const qid = amazonRootElement ? amazonRootElement.value : '';
const domain = window.location.hostname;
async function getInventory(asin, page = 1) {
const productScrapeUrl =
page === 1
? "https://" + domain + "/gp/product/ajax/ref=aod_f_new?asin=" + asin + "&m=&qid=&smid=&sourcecustomerorglistid=&sourcecustomerorglistitemid=&sr=&pc=dp&experienceId=aodAjaxMain"
: "https://" + domain + "/gp/product/ajax/ref=aod_page_" + page + "?asin=" + asin + "&m=&qid=" + qid + "&smid=&sourcecustomerorglistid=&sourcecustomerorglistitemid=&sr=8-1&pc=dp&isonlyrenderofferlist=true&pageno=" + page + "&experienceId=aodAjaxMain";
const response = await fetch(productScrapeUrl);
const cartPageText = await response.text();
const parser = new DOMParser();
const cartPageDoc = parser.parseFromString(cartPageText, "text/html");
if (page === 1) {
const product = cartPageDoc.querySelector(['[id="aod-pinned-offer"]']);
if (product) {
const stockData = extractStock(product);
if (stockData) {
inventory.push(stockData);
}
}
}
const offers = cartPageDoc.querySelectorAll('.aod-other-offer-block');
let stopScraping = false;
for (const offer of offers) {
const stockData = extractStock(offer);
const existing = inventory.filter((itm) => {
return stockData.seller_id === itm.seller_id && stockData.price === itm.price && stockData.condition === itm.condition;
});
if (existing && existing.length > 0) {
stopScraping = true;
} else {
inventory.push(stockData);
}
}
if (offers.length === 10 && stopScraping === false) {
page++;
await getInventory(asin, page);
}
}
const extractStock = function (element) {
const sellerLink = element.querySelector('[id="aod-offer-soldBy"] a');
const soldBy = element
.querySelector('[id="aod-offer-soldBy"]');
if (soldBy) {
let sellerId = '';
if (sellerLink) {
const sellerLinkHref = sellerLink.getAttribute('href');
const sellerLinkSearchParams = new URLSearchParams(sellerLinkHref);
sellerId = sellerLinkSearchParams.get('seller');
}
const sellerSpan = soldBy.firstElementChild.firstElementChild.lastElementChild.querySelector("span");
const seller = sellerLink
? sellerLink.textContent.trim()
: sellerSpan.textContent.trim();
let condition = element
.querySelector('[id="aod-offer-heading"] h4');
if (!condition) {
condition = element
.querySelector('[id="aod-offer-heading"]');
}
if (condition) {
condition = condition.textContent.trim()
.replace(/\s+/g, " ");
}
let price = element.querySelector('[class="a-offscreen"]').textContent.substr(1).trim();
if (!parseFloat(price)) {
price = element.querySelector('[class="aok-offscreen"]').textContent.trim().substr(1);
}
const quantity =
element.querySelectorAll('[id="aod-qty-dropdown-scroller"] > span').length +
1;
let sellerType = element
.querySelector('[id="aod-offer-shipsFrom"]>div')
.firstElementChild.lastElementChild.querySelector("span")
.textContent.trim();
let type =
sellerType === "Amazon" || sellerType === "Amazon.com"
? "FBA"
: "FBM";
const rating = element.querySelector(
'[id="seller-rating-count-{iter}"]>span'
);
let rating_count = null;
let rating_percentage = null;
if (rating) {
const ratingText = rating.innerHTML;
let currentNumber = "";
const numbers = [];
for (let i = 0; i < ratingText.length; i++) {
const char = ratingText.charAt(i);
if (!isNaN(char)) {
currentNumber += char;
} else if (currentNumber) {
numbers.push(parseInt(currentNumber));
currentNumber = "";
}
}
if (currentNumber) {
numbers.push(parseInt(currentNumber));
}
const trueNumbers = numbers.filter(num => !isNaN(num));
if (trueNumbers) {
rating_count = Number(trueNumbers[0]);
rating_percentage = parseFloat(trueNumbers[1]);
} else {
rating_count = 1;
rating_percentage = ratingText;
}
}
if (seller === "Amazon" || seller === "Amazon.com") {
type = "AMZ";
}
return {
'seller_name': seller,
'seller_id': sellerId,
'price': price,
'stocks': quantity,
'type': type,
'ratings_total': rating_count,
'ratings_percentage': rating_percentage,
'condition': condition,
'domain': domain,
};
}
};
await getInventory(scrapedASIN);
const newOffers = inventory.filter(n => n).filter((o) => o.condition === "New");
return newOffers;
}
const executeScript = async () => {
document.querySelector('[data-action=show-all-offers-display] a').click();
return new Promise(async (resolve, reject) => {
const scriptTimeout = setTimeout(() => {
reject(new Error('Script execution timed out'));
}, timeout);
window.addEventListener('message', async function(event) {
if (event.data && event.data.type === 'my-asin') {
const newOffers = await getAmazonSellerStockData(event.data.data);
clearTimeout(scriptTimeout);
resolve(JSON.stringify(newOffers));
}
});
});
};
Promise.race([
executeScript(),
new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Script execution timed out'));
}, timeout);
}),
])
.then((result) => {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'success',
data: result
}));
})
.catch((error) => {
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'error'
}));
});
`;
const AmazonProductPageWebView = ({
asin,
setAmazonData,
setAmazonStocksData,
setAmazonDataLoading,
amazonWebsite,
setAmazonOffers,
setFbaOffers,
setFbmOffers,
cacheSellerStock,
}) => {
const webViewRef = useRef(null);
const handleWebViewLoad = () => {
const data = {
'type': 'my-asin',
'data': asin,
};
const theData = JSON.stringify(data);
const messageToInject = `window.postMessage(${theData})`;
if (webViewRef && webViewRef.current) {
webViewRef.current.injectJavaScript(messageToInject);
}
};
const handleUnmount = () => {
webViewRef.current = null;
};
useEffect(() => {
return () => {
handleUnmount();
};
}, []);
const handleWebViewMessage = event => {
const data = JSON.parse(event.nativeEvent.data);
if (data && data.type === 'error') {
setAmazonDataLoading(false);
setAmazonStocksData([]);
setAlertVisible(true);
setAlertText('Something went wrong. Please try again.');
}
if (data && data.type === 'success' && data.data) {
const theData = JSON.parse(data.data);
if (theData && theData.length) {
setAmazonData(theData);
console.log('========');
console.log('SELLER STOCK');
console.log(JSON.stringify(theData));
console.log('========');
cacheSellerStock(asin, amazonWebsite, theData);
const stocksData = theData.map((itm) => {
return {
'stocks': itm.stocks,
'type': itm.type,
}
});
const amazonOffers = stocksData.filter(itm => itm.type === 'AMZ');
const fbaOffers = stocksData.filter(itm => itm.type === 'FBA');
const fbmOffers = stocksData.filter(itm => itm.type === 'FBM');
setAmazonOffers(amazonOffers.length);
setFbaOffers(fbaOffers.length);
setFbmOffers(fbmOffers.length);
setAmazonDataLoading(false);
setAmazonStocksData(stocksData);
setAlertVisible(false);
setAlertText('');
} else {
setAmazonDataLoading(false);
setAmazonStocksData([]);
setAlertVisible(true);
setAlertText(' No sellers found.');
}
} else {
setAmazonDataLoading(false);
setAmazonStocksData([]);
setAlertVisible(true);
setAlertText(' No sellers found.');
}
};
const onError = () => {
setAmazonDataLoading(false);
setAmazonStocksData([]);
setAlertVisible(true);
setAlertText(' No sellers found.');
}
const pageUrl = `https://www.amazon.${amazonWebsite}/dp/${asin}`;
const source = {
uri: pageUrl,
headers: {
'Cookie': 'session-id=262-0595900-4132742; i18n-prefs=GBP; ubid-acbuk=258-1963667-8125912; av-timezone=Asia/Manila; lc-acbuk=en_GB; session-id-time=2082787201l; sp-cdn="L5Z9:PH"; session-token=qUFm3afn6iSXDwaDVtq1H5/tjRi6f9lyepL1Kpxcr1fgB7pkyFwiSH8BIE17oBaGF7ZxQ47MyLcuVmMLd2JMrEHIA1hXBvEbKQx1xN+qJ/d6onImc5AXZhpxx0BGbHzifbiiys34xLAHInBjYRbe4VO9xBiuyt7bXlE/6Vu14JFguZQqKNW5plD8EHVSit7VfiWOfH5whI2J10egIjt2saLgbqz0Cr2Civ8slaz2opo8wO6t9uFOjMMT27saeSeEmOMOawh4Jlba4ReOU6oK/XrExMnP0QlrgMXvKwaCziCf2rBsq6g64fPvtBD6xzYvqngDoM8/RuT8orL6jTgw+94wZD7Oxak8gxjtJy/K6CE=; csm-hit=adb:adblk_yes&t:1693301769810&tb:SE46KWFE07QB5H7CKR5G+s-HS9QEFXRFXZ1SWPX5A6V|1693301769807'
}
};
const [alertVisible, setAlertVisible] = useState(false);
const [alertText, setAlertText] = useState('');
return (
<View>
{
alertVisible &&
<View style={{marginTop: 10}}>
<AlertBox type="warning" dismissable toggle={setAlertVisible}>
<LabelText color="valueText">
{alertText}
</LabelText>
</AlertBox>
</View>
}
<WebView
source={source}
javaScriptEnabled={true}
cacheEnabled={false}
incognito={true}
cacheMode={"LOAD_NO_CACHE"}
onMessage={handleWebViewMessage}
injectedJavaScript={injectScript}
onLoad={handleWebViewLoad}
onError={onError}
ref={webViewRef}
style={{ opacity: 0 }}
/>
</View>
);
};
const styles = StyleSheet.create({
normalPadding: {
padding: 10,
},
});
export default AmazonProductPageWebView;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment