2024-07-14 22:36:08 +03:00
|
|
|
import "./logger";
|
2024-07-14 16:49:40 +03:00
|
|
|
import { COUNTRIES } from "./countries";
|
2024-07-14 22:36:08 +03:00
|
|
|
import { initCache } from "./cache";
|
|
|
|
import { bookPriceFor } from "./bookPriceFor";
|
2024-07-14 16:49:40 +03:00
|
|
|
|
2024-07-14 22:36:08 +03:00
|
|
|
/*
|
|
|
|
TODO:
|
|
|
|
- not all currencies parsed as expected:
|
|
|
|
https://www.kobo.com/za/en/ebook/nine-minds
|
|
|
|
ZA: R300,60 -> $1,674.58
|
|
|
|
JP: 2,246 円 -> $Infinity
|
|
|
|
- publish to stores
|
|
|
|
- check in chrome
|
|
|
|
- more durable source for rates
|
|
|
|
- React for UI
|
|
|
|
- More informative, show loading progress
|
|
|
|
- clear stale cache
|
|
|
|
*/
|
|
|
|
|
|
|
|
const createPricesContainer = () => {
|
|
|
|
const pricingActionContainer = document
|
|
|
|
.querySelector(".primary-right-container")
|
|
|
|
.querySelector(".pricing-details")
|
|
|
|
.querySelector(".action-container");
|
|
|
|
|
|
|
|
const container = document.createElement("div");
|
|
|
|
|
|
|
|
container.style.display = "flex";
|
|
|
|
container.style.flexDirection = "column";
|
|
|
|
|
|
|
|
return pricingActionContainer.parentNode.insertBefore(
|
|
|
|
container,
|
|
|
|
pricingActionContainer,
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const getCountriesPrice = async () => {
|
|
|
|
const prices = [];
|
|
|
|
for (const country of COUNTRIES) {
|
|
|
|
// intentionally blocking execution
|
|
|
|
// to resolve sequentially.
|
|
|
|
// It should prevent DOS and triggering captcha
|
|
|
|
prices.push(await bookPriceFor(country));
|
|
|
|
}
|
|
|
|
|
|
|
|
return prices;
|
|
|
|
};
|
|
|
|
|
|
|
|
const formatPrice = (price) => {
|
|
|
|
const convertedPrice = price?.convertedPrice?.format ?? "NO PRICE";
|
|
|
|
|
|
|
|
const countryPrice = price?.countryPrice ?? "NO PRICE";
|
|
|
|
|
|
|
|
return `${price.countryCode.toUpperCase()}: ${countryPrice} -> ${convertedPrice}`;
|
|
|
|
};
|
|
|
|
|
|
|
|
const sortPrices = (prices) =>
|
|
|
|
prices.sort(
|
|
|
|
(a, b) =>
|
|
|
|
(a?.convertedPrice?.intValue || Infinity) -
|
|
|
|
(b?.convertedPrice?.intValue || Infinity),
|
|
|
|
);
|
|
|
|
|
|
|
|
const showPrices = (container, prices) => {
|
|
|
|
container.innerText = null;
|
|
|
|
prices.forEach((price) => {
|
|
|
|
const link = document.createElement("a");
|
|
|
|
link.href = price.url;
|
|
|
|
link.target = "_blank";
|
|
|
|
link.style.marginBottom = "5px";
|
|
|
|
link.innerText = formatPrice(price);
|
|
|
|
container.appendChild(link);
|
|
|
|
});
|
|
|
|
};
|
2024-07-14 16:49:40 +03:00
|
|
|
async function main() {
|
|
|
|
try {
|
2024-07-14 22:36:08 +03:00
|
|
|
initCache();
|
|
|
|
|
|
|
|
const container = createPricesContainer();
|
|
|
|
|
|
|
|
container.innerText = "LOADING PRICES...";
|
|
|
|
|
|
|
|
const countriesPrice = await getCountriesPrice();
|
2024-07-14 16:49:40 +03:00
|
|
|
|
2024-07-14 22:36:08 +03:00
|
|
|
l("country prices", countriesPrice);
|
2024-07-14 16:49:40 +03:00
|
|
|
|
2024-07-14 22:36:08 +03:00
|
|
|
sortPrices(countriesPrice);
|
2024-07-14 16:49:40 +03:00
|
|
|
|
2024-07-14 22:36:08 +03:00
|
|
|
l("sorted prices", countriesPrice);
|
2024-07-14 16:49:40 +03:00
|
|
|
|
2024-07-14 22:36:08 +03:00
|
|
|
showPrices(container, countriesPrice);
|
2024-07-14 16:49:40 +03:00
|
|
|
} catch (e) {
|
|
|
|
l("error", e);
|
|
|
|
} finally {
|
|
|
|
l("done");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
l("starting...");
|
|
|
|
|
|
|
|
window.onload = () => {
|
|
|
|
l("page is fully loaded");
|
|
|
|
void main();
|
|
|
|
};
|