User:Dagger/Widget drafts/API cache.js
From Guild Wars 2 Wiki
Jump to navigationJump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
var API = { key: localStorage.getItem("api-key"), perms: localStorage.getItem("api-key-permissions"), cacheTime: localStorage.getItem("api-cachetime") || 300 * 1000 /* 5 minutes */, updates: {}, endpoints: { "characters": { url: "https://api.guildwars2.com/v2/characters?wiki=1&page=0&page_size=200", requiresAuth: true, requiresPerms: ["characters"], postProcessing: function (data) { data.forEach(function (character, index) { // Pre-calculate a list of active crafting disciplines on this character. data[index].activeCrafting = []; character.crafting.forEach(function (craft) { if (craft.active) data[index].activeCrafting.push(craft.discipline.toLowerCase()); }); }); // Sort characters by play time. This is probably roughly what people want. return data.sort(function(a, b) { return a.age < b.age; }); }, }, "account/skins": { url: "https://api.guildwars2.com/v2/account/skins?wiki=1", requiresAuth: true, requiresPerms: ["unlocks"], }, "account/dyes": { url: "https://api.guildwars2.com/v2/account/dyes?wiki=1", requiresAuth: true, requiresPerms: ["unlocks"], }, "account/minis": { url: "https://api.guildwars2.com/v2/account/minis?wiki=1", requiresAuth: true, requiresPerms: ["unlocks"], }, "account/materials": { url: "https://api.guildwars2.com/v2/account/materials?wiki=1", requiresAuth: true, requiresPerms: ["inventories"], postProcessing: function(data) { // Reshape the response so we can look up materials by ID rather // than having to iterate through the whole array to find them. var items = {}; data.forEach(function(item) { items[item.id] = item; }); return items; }, }, "account/bank": { url: "https://api.guildwars2.com/v2/account/bank?wiki=1", requiresAuth: true, requiresPerms: ["inventories"], }, "account/wallet": { url: "https://api.guildwars2.com/v2/account/wallet?wiki=1", requiresAuth: true, requiresPerms: ["wallet"], postProcessing: function(data) { // Reshape the response so we can look up currencies by ID rather // than having to iterate through the whole array to find them. var currencies = {}; data.forEach(function(currency) { currencies[currency.id] = currency.value; }); return currencies; }, }, }, fetch: function API_fetchAPI(name) { var endpoint = this.endpoints[name]; // If this endpoint has already been requested, return the first request. if (this.updates[name]) { return this.updates[name]; } var dfr = new $.Deferred(); this.updates[name] = dfr.promise(); // If the API is disabled, don't resolve the promise -- just hang. // This exists to make testing code changes easier. if (localStorage.getItem("api-disabled")) { return this.updates[name]; } // If there's no API key set then don't do any queries. if (!API.key) { return dfr.reject("No API key set."); } // Check if our key has the required permissions for this query. No sense // in hitting the API endpoint constantly if it's just going to reject us. if (endpoint.requiresPerms && endpoint.requiresPerms.some(function(perm) { return API.perms.indexOf(perm) == -1 })) { return dfr.reject("API key is missing at least one necessary permission. Please set a new key."); } // Return the cached response if it's recent enough. var cacheKey = "api-cache-" + name; var cachedResponse = localStorage.getItem(cacheKey); var cachedResponseAge = new Date() - new Date(localStorage.getItem(cacheKey + "-updated")); if (cachedResponse && cachedResponseAge < API.cacheTime) { API.log("Using cached response for " + name); dfr.resolve(JSON.parse(cachedResponse)); } else { // It's not recent. Time to fetch from the API. var url = endpoint.url; if (endpoint.requiresAuth) { url += (url.indexOf('?') > -1 ? "&" : "?"); url += "access_token=" + this.key; } API.log("Querying API: " + url); $.getJSON(url).then(function(data) { if (endpoint.postProcessing) data = endpoint.postProcessing(data); localStorage.setItem(cacheKey, JSON.stringify(data)); localStorage.setItem(cacheKey + "-updated", new Date().toISOString()); dfr.resolve(data); }, function onFail(reason) { dfr.reject(reason); }); } return this.updates[name]; }, log: function API_log() { if (console && console.log) console.log.apply(console, arguments); }, } // If a key is set, show all API-related elements. if (API.key) $(".api.hide").removeClass("hide"); // Load the other scripts. If we don't do this from this page, these scripts end up racing this one... importScript("User:Dagger/Widget drafts/API recipe unlocks.js"); importScript("User:Dagger/Widget drafts/API item counts.js"); importScript("User:Dagger/Widget drafts/API mini unlocks.js"); importScript("User:Dagger/Widget drafts/API dye unlocks.js"); importScript("User:Dagger/Widget drafts/API skin unlocks.js"); importScript("User:Dagger/Widget drafts/API wallet.js"); importScript("User:Dagger/Widget drafts/API preferences.js"); // This should be in a <style> element in the final widget. var style = document.createElement("style"); document.querySelector("head").appendChild(style); style.sheet.insertRule(".api-craftinginactive { opacity: 0.5; }", 0);