all currencies converted correctly
This commit is contained in:
		
							parent
							
								
									64c26ab368
								
							
						
					
					
						commit
						f1947c0e00
					
				
					 6 changed files with 125 additions and 83 deletions
				
			
		|  | @ -1,4 +1,3 @@ | |||
| import currency from "currency.js"; | ||||
| import { bookUrl } from "./bookUrl"; | ||||
| import { extractPriceFrom } from "./extractPriceFrom"; | ||||
| import { getRate } from "./rates"; | ||||
|  | @ -22,18 +21,13 @@ export const bookPriceFor = async (country) => { | |||
|   let convertedPrice; | ||||
| 
 | ||||
|   if (countryPrice) { | ||||
|     l("found price", countryPrice, url); | ||||
|     const rate = await getRate(country.currencyCode); | ||||
| 
 | ||||
|     l("rate for", country.currencyCode, "is", rate); | ||||
| 
 | ||||
|     convertedPrice = currency(countryPrice).divide(rate); | ||||
| 
 | ||||
|     convertedPrice = { | ||||
|       intValue: convertedPrice.intValue, | ||||
|       format: convertedPrice.format(), | ||||
|     }; | ||||
| 
 | ||||
|     l("converted price for", country.currencyCode, convertedPrice); | ||||
|     convertedPrice = await convertedPrice( | ||||
|       countryPrice, | ||||
|       country.currencyCode, | ||||
|       rate, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   const newPrice = { | ||||
|  |  | |||
							
								
								
									
										46
									
								
								lib/convertPrice.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								lib/convertPrice.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| import currency from "currency.js"; | ||||
| 
 | ||||
| export 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(), | ||||
|   }; | ||||
| }; | ||||
|  | @ -6,44 +6,44 @@ export const COUNTRIES = [ | |||
|   { countryCode: "za", currencyCode: "zar" }, | ||||
|   { countryCode: "au", currencyCode: "aud" }, | ||||
|   { countryCode: "hk", currencyCode: "hkd" }, | ||||
|   { countryCode: "jp", currencyCode: "JPY" }, | ||||
|   // { countryCode: "my", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "nz", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "ph", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "sg", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "tw", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "th", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "at", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "be", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "cy", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "cz", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "dk", currencyCode: "EUR" },
 | ||||
|   // { 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: "EUR" },
 | ||||
|   // { countryCode: "pl", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "pt", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "ro", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "sk", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "si", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "es", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "se", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "ch", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "tr", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "gb", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "ar", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "br", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "cl", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "co", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "mx", currencyCode: "EUR" },
 | ||||
|   // { countryCode: "pe", currencyCode: "EUR" },
 | ||||
|   { 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" }, | ||||
| ]; | ||||
|  |  | |||
|  | @ -40,7 +40,11 @@ export const extractPriceFrom = async (url) => { | |||
| 
 | ||||
|     l("starting observing price on", url); | ||||
| 
 | ||||
|     return await observePriceOnPage(iframe.contentDocument.body, url); | ||||
|     const price = await observePriceOnPage(iframe.contentDocument.body, url); | ||||
| 
 | ||||
|     document.body.removeChild(iframe); | ||||
| 
 | ||||
|     return price; | ||||
|   } catch (e) { | ||||
|     l("getPriceForCountry", e, url); | ||||
|     return ""; | ||||
|  |  | |||
							
								
								
									
										48
									
								
								lib/index.js
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								lib/index.js
									
										
									
									
									
								
							|  | @ -5,28 +5,26 @@ import { bookPriceFor } from "./bookPriceFor"; | |||
| 
 | ||||
| /* | ||||
| 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 | ||||
| - More informative UI, show loading progress | ||||
| - clear stale cache | ||||
| - readme how to use and debug | ||||
| - configuration (purge cache, change base currency) | ||||
| */ | ||||
| 
 | ||||
| const createPricesContainer = () => { | ||||
|   const pricingActionContainer = document | ||||
|     .querySelector(".primary-right-container") | ||||
|     .querySelector(".pricing-details") | ||||
|     .querySelector(".action-container"); | ||||
|   const pricingActionContainer = document.querySelector( | ||||
|     ".primary-right-container", | ||||
|   ); | ||||
| 
 | ||||
|   const container = document.createElement("div"); | ||||
| 
 | ||||
|   container.style.display = "flex"; | ||||
|   container.style.flexDirection = "column"; | ||||
|   container.style.border = "1px solid black"; | ||||
|   container.style.padding = "10px"; | ||||
| 
 | ||||
|   return pricingActionContainer.parentNode.insertBefore( | ||||
|     container, | ||||
|  | @ -34,7 +32,7 @@ const createPricesContainer = () => { | |||
|   ); | ||||
| }; | ||||
| 
 | ||||
| const getCountriesPrice = async () => { | ||||
| const getPrices = async () => { | ||||
|   const prices = []; | ||||
|   for (const country of COUNTRIES) { | ||||
|     // intentionally blocking execution
 | ||||
|  | @ -46,14 +44,6 @@ const getCountriesPrice = async () => { | |||
|   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) => | ||||
|  | @ -68,19 +58,28 @@ const showPrices = (container, prices) => { | |||
|     link.href = price.url; | ||||
|     link.target = "_blank"; | ||||
|     link.style.marginBottom = "5px"; | ||||
|     link.innerText = formatPrice(price); | ||||
|     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); | ||||
|   }); | ||||
| }; | ||||
| async function main() { | ||||
|   try { | ||||
|     initCache(); | ||||
| 
 | ||||
| async function main() { | ||||
|   const container = createPricesContainer(); | ||||
| 
 | ||||
|   container.innerText = "LOADING PRICES..."; | ||||
| 
 | ||||
|     const countriesPrice = await getCountriesPrice(); | ||||
|   try { | ||||
|     initCache(); | ||||
| 
 | ||||
|     const countriesPrice = await getPrices(); | ||||
| 
 | ||||
|     l("country prices", countriesPrice); | ||||
| 
 | ||||
|  | @ -91,6 +90,7 @@ async function main() { | |||
|     showPrices(container, countriesPrice); | ||||
|   } catch (e) { | ||||
|     l("error", e); | ||||
|     container.innerText = "FAILED TO LOAD PRICES. CHECK CONSOLE FOR MORE INFO"; | ||||
|   } finally { | ||||
|     l("done"); | ||||
|   } | ||||
|  |  | |||
|  | @ -4,12 +4,10 @@ import { getRates, cacheRates } from "./cache"; | |||
| export const baseCurrency = "usd"; | ||||
| 
 | ||||
| export const loadCurrencyRates = async () => { | ||||
|   l("loading currency rates"); | ||||
| 
 | ||||
|   try { | ||||
|     const res = await fetch( | ||||
|       `https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/${baseCurrency}.json`, | ||||
|     ); | ||||
|     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); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue