// ==UserScript== // @name Kobo Price // @namespace https://tertyshny.dev // @description Find lowest book price on kobo.com // @noframes // @match https://www.kobo.com/*/*/ebook/* // @match https://www.kobo.com/*/*/audiobook/* // @require https://cdn.jsdelivr.net/npm/currency.js // @require https://cdn.jsdelivr.net/npm/date-fns/cdn.min.js // @run-at document-end // @version 1 // @icon data:image/png;base64,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 // ==/UserScript== globalThis.l = (...m) => console.log("KOBOPRICE", ...m); const COUNTRIES = [ { countryCode: "ww", currencyCode: "usd" }, { countryCode: "ca", currencyCode: "cad" }, { countryCode: "us", currencyCode: "usd" }, { countryCode: "in", currencyCode: "inr" }, { countryCode: "za", currencyCode: "zar" }, { countryCode: "au", currencyCode: "aud" }, { countryCode: "hk", currencyCode: "hkd" }, { countryCode: "jp", currencyCode: "jpy" }, { countryCode: "my", currencyCode: "myr" }, { countryCode: "nz", currencyCode: "nzd" }, { countryCode: "ph", currencyCode: "php" }, { countryCode: "sg", currencyCode: "sgd" }, { countryCode: "tw", currencyCode: "twd" }, { countryCode: "th", currencyCode: "usd" }, { countryCode: "at", currencyCode: "eur" }, { countryCode: "be", currencyCode: "eur" }, { countryCode: "cy", currencyCode: "eur" }, { countryCode: "cz", currencyCode: "czk" }, { countryCode: "dk", currencyCode: "dkk" }, { countryCode: "ee", currencyCode: "eur" }, { countryCode: "fi", currencyCode: "eur" }, { countryCode: "fr", currencyCode: "eur" }, { countryCode: "de", currencyCode: "eur" }, { countryCode: "gr", currencyCode: "eur" }, { countryCode: "ie", currencyCode: "eur" }, { countryCode: "it", currencyCode: "eur" }, { countryCode: "lt", currencyCode: "eur" }, { countryCode: "lu", currencyCode: "eur" }, { countryCode: "mt", currencyCode: "eur" }, { countryCode: "nl", currencyCode: "eur" }, { countryCode: "no", currencyCode: "nok" }, { countryCode: "pl", currencyCode: "pln" }, { countryCode: "pt", currencyCode: "eur" }, { countryCode: "ro", currencyCode: "ron" }, { countryCode: "sk", currencyCode: "eur" }, { countryCode: "si", currencyCode: "eur" }, { countryCode: "es", currencyCode: "eur" }, { countryCode: "se", currencyCode: "sek" }, { countryCode: "ch", currencyCode: "chf" }, { countryCode: "tr", currencyCode: "try" }, { countryCode: "gb", currencyCode: "gbp" }, { countryCode: "ar", currencyCode: "usd" }, { countryCode: "br", currencyCode: "brl" }, { countryCode: "cl", currencyCode: "clp" }, { countryCode: "co", currencyCode: "cop" }, { countryCode: "mx", currencyCode: "mxn" }, { countryCode: "pe", currencyCode: "pen" }, ]; const CACHE_PREFIX = "KOBOPRICE"; const initCache = () => { if (!localStorage.getItem(CACHE_PREFIX)) { setState({ books: {}, rates: null }); } }; const getState = () => JSON.parse(localStorage.getItem(CACHE_PREFIX)); const setState = (s) => localStorage.setItem(CACHE_PREFIX, JSON.stringify(s)); const getRates = () => getState().rates; const cacheRates = (rates) => setState({ ...getState(), rates }); const getBookPrice = (url) => getState().books[url]; const cacheBookPrice = (price, url) => { const state = getState(); state.books[url] = price; setState(state); }; const bookUrl = (country) => { const urlPattern = /^https:\/\/www\.kobo\.com\/../; const newPath = `https://www.kobo.com/${country}`; const url = window.location.href.replace(urlPattern, newPath); l("url for country", country, url); return url; }; const convertPrice = async (price, curr, rate) => { l("rate for", curr, "is", rate); let useVedic = false; switch (curr) { case "inr": case "php": { useVedic = true; break; } case "jpy": { break; } case "zar": { price = price.replace(",", "."); break; } case "dkk": { price = price.replace("kr.", "").replace(",", "."); break; } case "pen": { price = price.replace("S/.", ""); break; } case "clp": case "cop": case "twd": { break; } default: price = price.replace(/[^\d,.-]/, "").replace(",", "."); } const convertedPrice = currency(price, { useVedic }).divide(rate); l("converted price for", curr, convertedPrice); return { intValue: convertedPrice.intValue, formatted: convertedPrice.format(), }; }; const timeout = (duration) => new Promise((r) => setTimeout(r, duration)); const observePriceOnPage = (page) => new Promise((res, rej) => { timeout(10000).then(() => rej("price not found")); var observer = new MutationObserver(() => { const price = page?.querySelector( ".primary-right-container .pricing-details .active-price span", )?.textContent; if (price) { l("found price", price); observer.disconnect(); res(price); } }); observer.observe(page, { attributes: true, childList: true, characterData: true, subtree: true, }); }); const extractPrice = async (url) => { try { l("going to", url); const iframe = document.createElement("iframe"); iframe.src = url; iframe.hidden = true; document.body.append(iframe); await new Promise((res) => (iframe.contentWindow.onload = res)); l("starting observing price on", url); const price = await observePriceOnPage(iframe.contentDocument.body, url); document.body.removeChild(iframe); return price; } catch (e) { l("getPriceForCountry", e, url); return ""; } }; const baseCurrency = "usd"; const loadCurrencyRates = async () => { try { const url = `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/${baseCurrency}.json`; l("loading currency rates", url); const res = await fetch(url); return await res.json(); } catch (e) { l("loadCurrencyRates", e); return null; } }; const getRate = async (currency) => { const cached = getRates(); if (cached && dateFns.isToday(cached.date)) { l("found rates in cache", cached); return cached[baseCurrency][currency]; } const newRates = await loadCurrencyRates(); if (!newRates) { l("failed to download rates"); return 0; } l("new rates", newRates); cacheRates(newRates); return newRates[baseCurrency][currency]; }; const bookPriceFor = async (country) => { l("looking price for", country.countryCode); const url = bookUrl(country.countryCode); const fromCache = getBookPrice(url); if (fromCache && dateFns.isToday(fromCache.cachedAt)) { l("found book price in cache", fromCache); return fromCache; } const countryPrice = await extractPrice(url); let convertedPrice; if (countryPrice) { l("found price", countryPrice, url); const rate = await getRate(country.currencyCode); convertedPrice = await convertPrice( countryPrice, country.currencyCode, rate, ); } const newPrice = { ...country, countryPrice, convertedPrice, url, cachedAt: dateFns.format(new Date(), "yyyy-MM-dd"), }; cacheBookPrice(newPrice, url); return newPrice; }; const sortPrices = (prices) => prices.sort( (a, b) => (a?.convertedPrice?.intValue || Infinity) - (b?.convertedPrice?.intValue || Infinity), ); const getPrices = 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 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.style.display = "flex"; link.style.justifyContent = "space-between"; const oldPrice = document.createElement("p"); oldPrice.innerText = `${price.countryCode.toUpperCase()}: ${price?.countryPrice || "NO PRICE"}`; const newPrice = document.createElement("p"); newPrice.innerText = price?.convertedPrice?.formatted ?? "NO PRICE"; newPrice.style.fontWeight = "bold"; link.appendChild(oldPrice); link.appendChild(newPrice); container.appendChild(link); }); }; const createPricesContainer = () => { const pricingActionContainers = document.querySelectorAll(".pricing-details"); l("all pricing containers", pricingActionContainers); let visible; for (const node of pricingActionContainers) { if (node.checkVisibility()) { l("found visible pricing container", node); visible = node; break; } } const container = document.createElement("div"); container.style.display = "flex"; container.style.flexDirection = "column"; container.style.border = "1px solid black"; container.style.padding = "10px"; return visible.parentNode.insertBefore(container, visible); }; async function main() { const container = createPricesContainer(); container.innerText = "LOADING PRICES..."; try { initCache(); const countriesPrice = await getPrices(); l("country prices", countriesPrice); sortPrices(countriesPrice); l("sorted prices", countriesPrice); showPrices(container, countriesPrice); } catch (e) { l("error", e); container.innerText = "FAILED TO LOAD PRICES. CHECK CONSOLE FOR MORE INFO"; } finally { l("done"); } } l("starting..."); void main();