// API
        // API
        // API

        public async Task <ExchangeRateData> GetItemAsync()
        {
            ConfigData config = await ConfigDataProvider.GetConfigAsync();

            string jsFileName = GetJSFileName();

            using (ILockObject lockObject = await FileSystem.FileSystemProvider.LockResourceAsync(jsFileName)) {
                ExchangeRateData data = await DataProvider.GetAsync(KEY);

                if (data != null && data.SaveTime.Add(config.RefreshInterval) < DateTime.UtcNow)
                {
                    data = null;
                }
                if (data != null && !await FileSystem.FileSystemProvider.FileExistsAsync(jsFileName))
                {
                    data = null;
                }
                if (data == null)
                {
                    data = await GetExchangeRatesAsync();
                }
                await lockObject.UnlockAsync();

                return(data);
            }
        }
        private async Task SaveRatesJSAsync(ExchangeRateData data)
        {
            string        file = GetJSFileName();
            ScriptBuilder sb   = new ScriptBuilder();

            sb.Append("// Generated file (see ExchangeRateDataProvider) - Do not modify\n");
            sb.Append("YetaWF_CurrencyConverter_Rates = \n");
            sb.Append(Utility.JsonSerialize(data.Rates));
            sb.Append(";\n");
            await FileSystem.FileSystemProvider.WriteAllTextAsync(file, sb.ToString());
        }
        private async Task <ExchangeRateData> GetExchangeRatesAsync()
        {
            ConfigData config = await ConfigDataProvider.GetConfigAsync();

            if (string.IsNullOrWhiteSpace(config.AppID))
            {
                throw new InternalError("The App ID has not been specified in the Currency Converter Settings (see Admin > Configuration > Currency Converter Settings) - openexchangerates.org requires an app id to be able to retrieve currency exchange rates");
            }

            ExchangeRateData data = new ExchangeRateData();

            data.Key      = KEY;
            data.SaveTime = DateTime.UtcNow;

            string url  = string.Format("{0}://openexchangerates.org/api/latest.json?app_id={1}", config.UseHttps ? "https" : "http", config.AppID);
            string json = await GetJSONResponseAsync(url);

            CheckForErrors(json);

            url = string.Format("{0}://openexchangerates.org/api/currencies.json?app_id={1}", config.UseHttps ? "https" : "http", config.AppID);
            string jsonCurrencies = await GetJSONResponseAsync(url);

            CheckForErrors(jsonCurrencies);

            // get all currencies
            Dictionary <string, object> currencies = Utility.JsonDeserialize <Dictionary <string, object> >(jsonCurrencies);
            // add all rates
            dynamic jsonObject = Utility.JsonDeserialize(json);
            var     rates      = jsonObject.rates;

            foreach (var rate in rates)
            {
                string code = rate.Name;
                object currency;
                if (!currencies.TryGetValue(code, out currency))// replace 3 digit codes by actual name
                {
                    currency = code;
                }
                decimal val = (decimal)rate.Value;
                data.Rates.Add(new ExchangeRateEntry {
                    Code = code, CurrencyName = (string)currency, Rate = val
                });
            }
            // Save new rates
            UpdateStatusEnum status = await DataProvider.UpdateAsync(KEY, KEY, data);

            if (status != UpdateStatusEnum.OK)
            {
                if (status != UpdateStatusEnum.RecordDeleted)
                {
                    throw new InternalError("Unexpected status {0}", status);
                }
                if (!await DataProvider.AddAsync(data))
                {
                    throw new InternalError("Unexpected error adding data");
                }
            }
            // Create a javascript file with rates so we can include it in a page
            await SaveRatesJSAsync(data);

            return(data);
        }