diff --git a/RehauSku.Assist-AddIn.dna b/RehauSku.Assist-AddIn.dna index 7ead322..1bef6e1 100644 --- a/RehauSku.Assist-AddIn.dna +++ b/RehauSku.Assist-AddIn.dna @@ -8,23 +8,6 @@ - - - - + + + \ No newline at end of file diff --git a/RehauSku.Assist.csproj b/RehauSku.Assist.csproj index 63b4063..6f12a34 100644 --- a/RehauSku.Assist.csproj +++ b/RehauSku.Assist.csproj @@ -42,6 +42,9 @@ packages\ExcelDna.Integration.1.5.0\lib\net452\ExcelDna.Integration.dll False + + packages\ExcelDna.IntelliSense.1.5.0\lib\net452\ExcelDna.IntelliSense.dll + packages\ExcelDna.Registration.1.5.0\lib\net452\ExcelDna.Registration.dll True @@ -96,7 +99,10 @@ + + + diff --git a/Source/AddIn/AddIn.cs b/Source/AddIn/AddIn.cs index e29c070..5cae777 100644 --- a/Source/AddIn/AddIn.cs +++ b/Source/AddIn/AddIn.cs @@ -1,4 +1,5 @@ using ExcelDna.Integration; +using ExcelDna.IntelliSense; using ExcelDna.Registration; using Microsoft.Win32; using System.Net.Http; @@ -24,11 +25,12 @@ namespace RehauSku { RegisterFunctions(); GetRegistryKeys(); + IntelliSenseServer.Install(); } public void AutoClose() { - + IntelliSenseServer.Uninstall(); } void RegisterFunctions() diff --git a/Source/AddIn/Functions.cs b/Source/AddIn/Functions.cs index c6e9da4..2ae22e4 100644 --- a/Source/AddIn/Functions.cs +++ b/Source/AddIn/Functions.cs @@ -5,16 +5,52 @@ namespace RehauSku { public class Functions { - [ExcelFunction] - public static object RAUNAME(string request) - => SkuAssist.GetProduct(request, ProductField.Name); + [ExcelFunction(Description = "Получение названия первого продукта по запросу в интернет-магазин REHAU")] + public static object RAUNAME([ExcelArgument(Name = "Запрос", Description = "Запрос в свободной форме или ячейка с запросом")] string request) + => MakeRequest(request, ProductField.Name); - [ExcelFunction] - public static object RAUSKU(string request) - => SkuAssist.GetProduct(request, ProductField.Id); + [ExcelFunction(Description = "Получение артикула первого продукта по запросу в интернет-магазин REHAU")] + public static object RAUSKU([ExcelArgument(Name = "Запрос", Description = "Запрос в свободной форме или ячейка с запросом")] string request) + => MakeRequest(request, ProductField.Id); - [ExcelFunction] - public static object RAUPRICE(string request) - => SkuAssist.GetProduct(request, ProductField.Price); + [ExcelFunction(Description = "Получение цены первого продукта по запросу в интернет-магазин REHAU")] + public static object RAUPRICE([ExcelArgument(Name = "Запрос", Description = "Запрос в свободной форме или ячейка с запросом")] string request) + => MakeRequest(request, ProductField.Price); + + private static object MakeRequest(string request, ProductField field) + { + object result; + + if (request.IsCached()) + result = request.GetFromCache(); + + else + { + result = ExcelAsyncUtil.Run("Request", request, delegate + { + return request.RequestAndCache().GetAwaiter().GetResult(); + }); + } + + if (result == null) + return "Не найдено :("; + + if (result.Equals(ExcelError.ExcelErrorNA)) + return "Загрузка..."; + + IProduct product = result as IProduct; + + switch (field) + { + case ProductField.Name: + return product.Name; + case ProductField.Id: + return product.Id; + case ProductField.Price: + return double.Parse(product.Price, System.Globalization.CultureInfo.InvariantCulture); + default: + return null; + } + } } } \ No newline at end of file diff --git a/Source/Assistant/HttpClientUtil.cs b/Source/Assistant/HttpClientUtil.cs index 131bd7f..16e4287 100644 --- a/Source/Assistant/HttpClientUtil.cs +++ b/Source/Assistant/HttpClientUtil.cs @@ -1,6 +1,4 @@ -using AngleSharp; -using AngleSharp.Dom; -using System; +using System; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -11,8 +9,10 @@ namespace RehauSku.Assistant { private static HttpClient _httpClient = AddIn.httpClient; - public async static Task GetContentByUriAsync(Uri uri) + public async static Task GetContentByRequest(string request) { + Uri uri = request.ConvertToUri(); + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | @@ -21,15 +21,7 @@ namespace RehauSku.Assistant return await _httpClient.GetStringAsync(uri); } - public async static Task ContentToDocAsync(Task content) - { - IConfiguration config = Configuration.Default; - IBrowsingContext context = BrowsingContext.New(config); - - return await context.OpenAsync(req => req.Content(content.Result)); - } - - public static Uri ConvertToUri(this string request) + private static Uri ConvertToUri(this string request) { UriBuilder baseUri = new UriBuilder("https", "shop-rehau.ru"); diff --git a/Source/Assistant/MemoryCacheExtensions.cs b/Source/Assistant/MemoryCacheExtensions.cs new file mode 100644 index 0000000..7eb1408 --- /dev/null +++ b/Source/Assistant/MemoryCacheExtensions.cs @@ -0,0 +1,30 @@ +using System; +using System.Runtime.Caching; +using System.Threading.Tasks; + +namespace RehauSku.Assistant +{ + static class MemoryCacheExtensions + { + public static bool IsCached(this string request) + { + return MemoryCache.Default.Contains(request); + } + + public static IProduct GetFromCache(this string request) + { + return MemoryCache.Default[request] as IProduct; + } + + public static async Task RequestAndCache(this string request) + { + IProduct product = await SkuAssist.GetProductAsync(request); + + if (product == null) + return null; + + MemoryCache.Default.Add(request, product, DateTime.Now.AddMinutes(10)); + return product; + } + } +} \ No newline at end of file diff --git a/Source/Assistant/ParseUtil.cs b/Source/Assistant/ParseUtil.cs new file mode 100644 index 0000000..571c6b0 --- /dev/null +++ b/Source/Assistant/ParseUtil.cs @@ -0,0 +1,55 @@ +using AngleSharp; +using AngleSharp.Dom; +using Newtonsoft.Json; +using System; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace RehauSku.Assistant +{ + static class ParseUtil + { + public async static Task ContentToDocAsync(string content) + { + IConfiguration config = Configuration.Default; + IBrowsingContext context = BrowsingContext.New(config); + + return await context.OpenAsync(req => req.Content(content)); + } + + public static IProduct GetProduct(IDocument document) + { + try + { + string script = document + .Scripts + .Where(s => s.InnerHtml.Contains("dataLayer")) + .FirstOrDefault() + .InnerHtml; + + string json = script + .Substring(script.IndexOf("push(") + 5) + .TrimEnd(new[] { ')', ';', '\n', ' ' }); + + if (!json.Contains("impressions")) + return null; + + StoreResponce storeResponse = JsonConvert.DeserializeObject(json); + IProduct product = storeResponse + .Ecommerce + .Impressions + .Where(p => p.Id.IsRehauSku()) + .FirstOrDefault(); + + return product; + } + + catch (NullReferenceException e) + { + MessageBox.Show(e.Message, "Ошибка получения данных", MessageBoxButtons.OK, MessageBoxIcon.Error); + return null; + } + } + } +} \ No newline at end of file diff --git a/Source/Assistant/SkuAssist.cs b/Source/Assistant/SkuAssist.cs index 28d1503..6c68288 100644 --- a/Source/Assistant/SkuAssist.cs +++ b/Source/Assistant/SkuAssist.cs @@ -1,13 +1,4 @@ -using AngleSharp.Dom; -using ExcelDna.Integration; -using Newtonsoft.Json; -using System; -using System.Globalization; -using System.Linq; -using System.Runtime.Caching; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Windows.Forms; +using System.Threading.Tasks; namespace RehauSku.Assistant { @@ -20,91 +11,12 @@ namespace RehauSku.Assistant static class SkuAssist { - public static async Task GetProduct(string request) + public static async Task GetProductAsync(string request) { - Uri uri = request.ConvertToUri(); + var content = await HttpClientUtil.GetContentByRequest(request); + var document = await ParseUtil.ContentToDocAsync(content); - Task contentTask = Task.Run(() => HttpClientUtil.GetContentByUriAsync(uri)); - Task documentTask = await contentTask.ContinueWith(content => HttpClientUtil.ContentToDocAsync(content)); - - return GetProduct(documentTask.Result); - } - public static IProduct GetProduct(IDocument document) - { - try - { - string script = document - .Scripts - .Where(s => s.InnerHtml.Contains("dataLayer")) - .FirstOrDefault() - .InnerHtml; - - string json = script - .Substring(script.IndexOf("push(") + 5) - .TrimEnd(new[] { ')', ';', '\n', ' ' }); - - if (!json.Contains("impressions")) - return null; - - StoreResponce storeResponse = JsonConvert.DeserializeObject(json); - IProduct product = storeResponse - .Ecommerce - .Impressions - .Where(p => p.Id.IsRehauSku()) - .FirstOrDefault(); - - return product; - } - - catch (NullReferenceException e) - { - MessageBox.Show(e.Message, "Ошибка получения данных", MessageBoxButtons.OK, MessageBoxIcon.Error); - return null; - } - } - public static object GetProduct(string request, ProductField field) - { - IProduct product; - - if (MemoryCache.Default.Contains(request)) - { - product = MemoryCache.Default[request] as IProduct; - } - - else - { - object result = ExcelAsyncUtil.Run("RauName", new[] { request }, - delegate - { - Task p = Task.Run(() => GetProduct(request)); - return p.Result; - }); - - if (result == null) - return "Не найдено :("; - - if (result.Equals(ExcelError.ExcelErrorNA)) - return "Загрузка..."; - - product = result as IProduct; - MemoryCache.Default.Add(request, product, DateTime.Now.AddMinutes(10)); - } - - switch (field) - { - case ProductField.Name: - return product.Name; - case ProductField.Id: - return product.Id; - case ProductField.Price: - return double.Parse((string)product.Price, CultureInfo.InvariantCulture); - default: - return ExcelError.ExcelErrorValue; - } - } - public static bool IsRehauSku(this string line) - { - return Regex.IsMatch(line, @"^[1]\d{6}[1]\d{3}$"); + return ParseUtil.GetProduct(document); } } } \ No newline at end of file diff --git a/Source/Assistant/SkuExtension.cs b/Source/Assistant/SkuExtension.cs new file mode 100644 index 0000000..51aaf6c --- /dev/null +++ b/Source/Assistant/SkuExtension.cs @@ -0,0 +1,12 @@ +using System.Text.RegularExpressions; + +namespace RehauSku.Assistant +{ + static class SkuExtension + { + public static bool IsRehauSku(this string line) + { + return Regex.IsMatch(line, @"^[1]\d{6}[1]\d{3}$"); + } + } +} \ No newline at end of file diff --git a/Source/DataExport/Exporter.cs b/Source/DataExport/Exporter.cs index cc7621e..40a1d5d 100644 --- a/Source/DataExport/Exporter.cs +++ b/Source/DataExport/Exporter.cs @@ -52,7 +52,7 @@ namespace RehauSku.DataExport object current = SelectedCells[row, column]; if (current.GetType() == typeof(string) - && SkuAssist.IsRehauSku((string)current)) + && ((string)current).IsRehauSku()) sku = (string)current; else if (current.GetType() == typeof(string) diff --git a/packages.config b/packages.config index 9ede974..6e8f1d1 100644 --- a/packages.config +++ b/packages.config @@ -3,6 +3,7 @@ +