diff --git a/exec/load/openweathermap.js b/exec/load/openweathermap.js new file mode 100644 index 0000000000000000000000000000000000000000..f4ece2db83c15fbf8f8fcbdfedb4f25f37d909a1 --- /dev/null +++ b/exec/load/openweathermap.js @@ -0,0 +1,64 @@ +// Uses OpenWeatherMap, openweathermap.org +// CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0/ +// Sign up for your account & API key here: https://openweathermap.org/api +// Add an [openweathermap] section to modopts.ini +// Add an api_key value to that section with your key +// rate_window, rate_limit, and data_refresh values can be added as well, +// but the defaults are suited to the free tier. + +load('http.js'); +load('modopts.js'); + +function OpenWeatherMap() { + this.settings = get_mod_options('openweathermap'); + if (!this.settings.rate_window) this.settings.rate_window = 60; // Seconds + if (!this.settings.rate_limit) this.settings.rate_limit = 60; // Requests per window + if (!this.settings.data_refresh) this.settings.data_refresh = 7200; // Seconds + this.cache = {}; + this.requests = []; +} + +OpenWeatherMap.prototype.write_cache = function (endpoint, params, response) { + const hash = base64_encode(endpoint + JSON.stringify(params)); + this.cache[hash] = { time: time(), data: response }; +} + +OpenWeatherMap.prototype.read_cache = function (endpoint, params) { + const hash = base64_encode(endpoint + JSON.stringify(params)); + if (!this.cache[hash]) return; + // This is probably not the right way, but it'll do + if (time() - this.cache[hash].time > this.settings.data_refresh) return; + return this.cache[hash].data; +} + +OpenWeatherMap.prototype.rate_limit = function () { + const now = time(); + this.requests = this.requests.filter(function (e) { + return now - e < this.settings.rate_window; + }, this); + if (this.requests.length < this.settings.rate_limit) { + this.requests.push(now); + return true; + } else { + return false; + } +} + +OpenWeatherMap.prototype.call_api = function (endpoint, params) { + + const cache = this.read_cache(endpoint, params); + if (cache) return cache; + + if (!this.rate_limit()) return { error: 'Rate limit exceeded' }; + + var url = 'http://api.openweathermap.org/data/2.5/' + endpoint; + url += Object.keys(params).reduce(function (a, c, i) { + return a + (i == 0 ? '?' : '&') + c + '=' + params[c]; + }, ''); + url += '&APPID=' + this.settings.api_key; + + const response = JSON.parse((new HTTPRequest()).Get(url)); + this.write_cache(endpoint, params, response); + + return response; +}