using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Props.Shop.Adafruit.Api; using Props.Shop.Adafruit.Persistence; using Props.Shop.Framework; namespace Props.Shop.Adafruit { public class AdafruitShop : IShop { private string workspaceDir; private ILoggerFactory loggerFactory; private ILogger logger; private SearchManager searchManager; private Configuration configuration; private HttpClient http; private bool disposedValue; public string ShopName => "Adafruit"; public string ShopDescription => "A electronic component online hardware company."; public string ShopModuleAuthor => "Reslate"; public SupportedFeatures SupportedFeatures => new SupportedFeatures( false, false, false, false, true ); public void Initialize(string workspaceDir, ILoggerFactory loggerFactory) { this.workspaceDir = workspaceDir; this.loggerFactory = loggerFactory; logger = loggerFactory.CreateLogger(); http = new HttpClient(); http.BaseAddress = new Uri("http://www.adafruit.com/api/"); try { configuration = JsonSerializer.Deserialize(File.ReadAllText(Path.Combine(workspaceDir, Configuration.FILE_NAME))); } catch (JsonException) { logger.LogWarning("Could not read JSON file."); } catch (ArgumentException) { logger.LogWarning("No working directory path provided."); } catch (DirectoryNotFoundException) { logger.LogWarning("Directory could not be found."); } catch (FileNotFoundException) { logger.LogWarning("File could not be found."); } finally { if (configuration == null) { configuration = new Configuration(); } } ProductListingCacheData listingData = null; try { listingData = JsonSerializer.Deserialize(File.ReadAllText(Path.Combine(workspaceDir, ProductListingCacheData.FILE_NAME))); if (listingData.LastUpdatedUtc - DateTime.UtcNow > TimeSpan.FromMilliseconds(configuration.CacheLifespan)) { listingData = null; } } catch (JsonException) { logger.LogWarning("Could not read JSON file."); } catch (ArgumentException) { logger.LogWarning("No working directory path provided."); } catch (DirectoryNotFoundException) { logger.LogWarning("Directory could not be found."); } catch (FileNotFoundException) { logger.LogWarning("File could not be found."); } finally { if (configuration == null) { configuration = new Configuration(); } } LiveProductListingManager productListingManager = new LiveProductListingManager(http, loggerFactory.CreateLogger(), listingData?.ProductListings, configuration.MinDownloadInterval); this.searchManager = new SearchManager(productListingManager, configuration.Similarity); productListingManager.StartUpdateTimer(delay: 0, configuration.CacheLifespan); } public async Task GetProductFromIdentifier(string identifier) { return await searchManager.ProductListingManager.GetProductListingFromIdentifier(identifier); } public IAsyncEnumerable Search(string query, Filters filters) { return searchManager.Search(query); } protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { http.Dispose(); searchManager.Dispose(); } disposedValue = true; } } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } public async ValueTask SaveData() { if (workspaceDir != null) { await File.WriteAllTextAsync(Path.Combine(workspaceDir, Configuration.FILE_NAME), JsonSerializer.Serialize(configuration)); await File.WriteAllTextAsync( Path.Combine(workspaceDir, configuration.ProductListingCacheFileName), JsonSerializer.Serialize(new ProductListingCacheData(await searchManager.ProductListingManager.ProductListings)) ); } } } }