Auto Fetching of Images (continuation of PR #45)
From @TinyRaindrop:
Would this be a logical next step? Force recheck for new images whenever game version changes. So that users get new data even before a new Runebook update is released.
Generally this should be the way to go, after finding a backup in case something of DDragon doesn't work, fails to update or anything like that. Potentially just using a github repo as cdn-ish replacement with backup static data ?
I think every installation can have such data stored locally in an Images folder, it's only 1-2 MB and users are querying for this data anyway every time they open Runebook.
Cache whatever is reasonable to cache (images, jsons), and when Runebook breaks on another update, users will have a fallback dataset.
As for the pictures. I don't know if we have to redo every patch. That's like 2,5MB every patch for nothing. With the runes or champs the tooltips or something like that change from time to time. But the pictures of the runes?
If we do this we should do it right. Don't blunt download. But send HEAD requests to the server and compare the ETags. That way we can do a delta comparison and wouldn't have to update obtuse all the time.
We could also create a file for the ETags and use that for the downloads of the jsons. If possible I will make a proof of concept tomorrow which we can use for the pictures of the runes.
By the way, NOW is a good time for a new version. Since we are planning small structure changes now.
@TinyRaindrop Yup, caching seems like the way to go definitely. @Rerago Absolutely, no need to spam the servers with requests In general we still have to make sure that in a situation where something with fetching it goes wrong, and a user is on a clean install without cache, we still have some kind of fallback to get the images.
And about release, will happen in a few minutes, since I would like to release auto upload with the same release.
Here's how it works:
var Store = require('electron-store');
var rp = require('request-promise-native');
const cacheStore = new Store({
name: "cache"
});
async function requestCachedAsync(url, cachePath){
// Determine etag from server
var etagResponse = await rp({ method: 'HEAD', uri: url, resolveWithFullResponse: true }).then(function(response) {
return response.headers["etag"] ?? '';
});
// Return variable
var response = null;
// is there an Etag? Trying to determine cache
if(etagResponse !== ''){
// determine etag from cache and return cached data if necessary
let etagCache = cacheStore.get(cachePath + '_etag');
if(etagCache == etagResponse){
response = cacheStore.get(cachePath);
console.log('ETag-Cached: ' + url);
}
}
// no cache? Download normally and store in cache
if(response === null){
// Downloading data normally
let normalResponse = await rp({ uri: url, resolveWithFullResponse: true }).then(function(resp) { return resp; })
// Error? Throw error
if(normalResponse.statusCode !== 200){
throw Error('Error Downloading: ' + url)
}
// determine etag
let responseEtag = normalResponse.headers['etag'];
// adapt return
response = normalResponse.body
// do you have data and a tag? => cache
if(response !== null && responseEtag != ''){
// Prepare cache data
let cachToSave = {};
cachToSave[cachePath] = response;
cachToSave[cachePath + '_etag'] = responseEtag;
// cache data
cacheStore.set(cachToSave);
}
}
// Return
return response;
}
And then like this for version.json
try{
requestCachedAsync('https://ddragon.leagueoflegends.com/api/versions.json', 'catch.versions_json').then(function (responsData) {
var ver = JSON.parse(responsData);
freezer.get().set('lolversions', ver);
freezer.emit("version:set", ver[0]);
});
}
catch {
throw Error("Couldn't get ddragon api version");
}
But I'm not really satisfied. The data is stored as JSON and not as a separate file. Which is later unfavorable for the images. Since we want to use them as reference.
This variant works quite well for JSON. But it is simply not worth it. Since we save ~200kb with it. But to do such a conversion is questionable.
For the pictures it would be worth it. The only problem is that the current pictures are bound to the exe and they are not located locally, so we can't replace them on the fly.