diff --git a/src/content/config.ts b/src/content/config.ts
index 41e0477..282de8d 100644
--- a/src/content/config.ts
+++ b/src/content/config.ts
@@ -3,6 +3,9 @@ export const storage_lastUpdateTime = 'tf2wikipricing_lastUpdate';
export const storage_schema = 'tf2wikipricing_schema';
export const storage_version = 'tf2wikipricing_version';
export const storage_priceprefix = 'tf2wikipricing_sku_';
+export const storage_exchangerates = 'tf2wikipricing_exchangerates';
+export const storage_exchangerates_update = 'tf2wikipricing_exchangerates_update';
+export const storage_exchangerates_next = 'tf2wikipricing_exchangerates_next';
export const conversion_ref_usd = 0.0265;
export const defindex_key = 5021;
export const defindex_metal_refined = 5002;
diff --git a/src/content/content.ts b/src/content/content.ts
index 1d8cbb5..288fe02 100644
--- a/src/content/content.ts
+++ b/src/content/content.ts
@@ -9,7 +9,9 @@ import { fetchPrice, fetchKeyPrice, ItemPriceData } from './priceService'
import { createPriceRow, createStoreButton } from './uiRenderer'
import { findFirstElement, findFirstChildElement } from './utils/dom'
import { extractPageTitleFromURL } from './utils/url';
+import { ExchangeRates, prepareExchangeRates } from './exchangeRateService';
var itemSchema: ItemSchema | null;
+var exchangeRates: ExchangeRates | null;
var locale: string = 'en'
@@ -425,7 +427,8 @@ async function inject() {
label.style.fontSize = "85%";
const updateText = $T("Updated %@.", locale).replace('%@', updateTime.toLocaleString(locale, { year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit', timeZoneName: 'short' }))
const attributionText = $T("Trade prices sourced from %@. Currency conversions are approximate.", locale).replace('%@', 'prices.tf');
- label.innerHTML = `${updateText}
${attributionText}`;
+ const exchangeRateAttribution = `Rates By Exchange Rate API.`;
+ label.innerHTML = `${updateText}
${attributionText}
${exchangeRateAttribution}`;
row.appendChild(label);
priceProgressRow.insertAdjacentElement('afterend', row);
@@ -440,15 +443,22 @@ function addStyles() {
style.innerHTML = styleCss;
}
-prepareSchema().then(function (schema) {
+prepareSchema()
+.then(schema => {
itemSchema = schema;
if (!itemSchema) {
- logError("No item schema ready, exiting.");
wipeSchema(); // FIXME: ugly hack. requires additional page reload. if prepareSchema returns null, we should handle it properly
- return;
+ throw new Error("No item schema ready");
}
+})
+.then(prepareExchangeRates)
+.then(rates => exchangeRates = rates)
+.then(() => {
locale = extractLocaleFromURL(document.URL)
addStyles();
inject();
// TODO: Purge expired price data
-});
\ No newline at end of file
+})
+.catch((error) => {
+ logError(error);
+})
\ No newline at end of file
diff --git a/src/content/exchangeRateService.ts b/src/content/exchangeRateService.ts
new file mode 100644
index 0000000..fe3a24a
--- /dev/null
+++ b/src/content/exchangeRateService.ts
@@ -0,0 +1,55 @@
+import { getStorageValue, setStorageValue } from './storage'
+import { logDebug, log, logError } from './utils/log'
+import { storage_exchangerates, storage_exchangerates_next, storage_exchangerates_update } from './config'
+declare function GM_fetch(input: string | URL | globalThis.Request, init?: RequestInit): Promise
+import './GM_fetch'
+
+export interface ExchangeRates {
+ [key: string]: number;
+}
+
+export async function wipeExchangeRates(): Promise {
+ await setStorageValue(storage_exchangerates, null)
+ await setStorageValue(storage_exchangerates_update, new Date().toISOString())
+ await setStorageValue(storage_exchangerates_next, new Date().toISOString())
+ logDebug(`Exchange rates wiped`)
+}
+
+export async function prepareExchangeRates(): Promise {
+ var needsUpdate: Boolean = false
+ var rates: ExchangeRates | null = null
+
+ rates = await getStorageValue(storage_exchangerates, null);
+ const update = await getStorageValue(storage_exchangerates_update, null)
+ const nextUpdate = await getStorageValue(storage_exchangerates_next, null)
+ if (update && nextUpdate) {
+ const lastUpdateTime = new Date(update);
+ const nextUpdateTime = new Date(nextUpdate);
+ log(`Exchange rates updated at ${lastUpdateTime}`);
+ if (rates == null || Object.keys(rates).length === 0 || lastUpdateTime.getTime() > nextUpdateTime.getTime()) {
+ needsUpdate = true
+ }
+ } else {
+ needsUpdate = true
+ }
+
+ if(needsUpdate) {
+ log("Exchange rates out of Date. Rebuilding...");
+ const url = "https://open.er-api.com/v6/latest/USD"
+ const response = await GM_fetch(url);
+ if (response.ok) {
+ await setStorageValue(storage_exchangerates_update, new Date().toISOString())
+ var json = await response.json()
+ if(json != null){
+ rates = json['rates']
+ await setStorageValue(storage_exchangerates, rates)
+ await setStorageValue(storage_exchangerates_next, json['time_next_update_utc'])
+ }
+ logDebug(`Exchange rates updated at ${new Date()}`)
+ } else {
+ logError(`Failed to fetch exchange rates. Status code: ${response.status}`, response)
+ }
+ }
+
+ return rates
+}