props/Props/Services/Modules/LocalShopManager.cs

107 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Props.Models.Search;
using Props.Options;
using Props.Shop.Framework;
namespace Props.Services.Modules
{
public class LocalShopManager : IShopManager
{
private ILogger<LocalShopManager> logger;
private Dictionary<string, IShop> shops;
private ModulesOptions options;
private IConfiguration configuration;
public LocalShopManager(IConfiguration configuration, ILogger<LocalShopManager> logger)
{
this.configuration = configuration;
this.logger = logger;
options = configuration.GetSection(ModulesOptions.Modules).Get<ModulesOptions>();
shops = new Dictionary<string, IShop>();
foreach (IShop shop in LoadShops(options.ShopsDir, options.ShopRegex, options.RecursiveLoad))
{
if (!shops.TryAdd(shop.ShopName, shop))
{
logger.LogWarning("Duplicate shop {0} detected. Ignoring the latter.", shop.ShopName);
}
}
}
public IEnumerable<string> AvailableShops()
{
return shops.Keys;
}
public async Task<IList<ProductListing>> Search(string query, SearchOutline searchOutline)
{
List<ProductListing> results = new List<ProductListing>();
foreach (string shopName in shops.Keys)
{
if (!searchOutline.Disabled[shopName])
{
int amount = 0;
await foreach (ProductListing product in shops[shopName].Search(query, searchOutline.Filters))
{
if (searchOutline.Filters.Validate(product))
{
amount += 1;
results.Add(product);
}
if (amount >= options.MaxResults) break;
}
}
}
return results;
}
private IEnumerable<IShop> LoadShops(string shopsDir, string shopRegex, bool recursiveLoad)
{
Stack<string> directories = new Stack<string>();
directories.Push(shopsDir);
string currentDirectory = null;
while (directories.TryPop(out currentDirectory))
{
if (recursiveLoad)
{
foreach (string dir in Directory.EnumerateDirectories(currentDirectory))
{
directories.Push(dir);
}
}
foreach (string file in Directory.EnumerateFiles(currentDirectory))
{
if (Path.GetExtension(file).Equals(".dll") && Regex.IsMatch(file, shopRegex))
{
ShopAssemblyLoadContext context = new ShopAssemblyLoadContext(file);
Assembly assembly = context.LoadFromAssemblyName(new AssemblyName(Path.GetFileNameWithoutExtension(file)));
int success = 0;
foreach (Type type in assembly.GetTypes())
{
if (typeof(IShop).IsAssignableFrom(type))
{
IShop shop = Activator.CreateInstance(type) as IShop;
if (shop != null)
{
success += 1;
yield return shop;
}
}
}
if (success == 0)
{
logger.LogWarning("There were no shops found within the assembly at path \"{0}\".", file);
}
}
}
}
}
}
}