diff --git a/EbayListingTool/Services/EbayAspectsService.cs b/EbayListingTool/Services/EbayAspectsService.cs new file mode 100644 index 0000000..b6c8a0a --- /dev/null +++ b/EbayListingTool/Services/EbayAspectsService.cs @@ -0,0 +1,74 @@ +using System.Net.Http.Headers; +using Newtonsoft.Json.Linq; + +namespace EbayListingTool.Services; + +public class CategoryAspect +{ + public string Name { get; set; } = ""; + public bool IsRequired { get; set; } + public bool IsFreeText { get; set; } = true; + public List AllowedValues { get; set; } = new(); +} + +public class EbayAspectsService +{ + private readonly EbayAuthService _auth; + private static readonly HttpClient _http = new(); + private readonly Dictionary> _cache = new(); + + public EbayAspectsService(EbayAuthService auth) => _auth = auth; + + public async Task> GetAspectsAsync(string categoryId) + { + if (string.IsNullOrWhiteSpace(categoryId)) return new(); + if (_cache.TryGetValue(categoryId, out var cached)) return cached; + + var token = await _auth.GetAppTokenAsync(); + var url = $"{_auth.BaseUrl}/commerce/taxonomy/v1/category_tree/3" + + $"/get_item_aspects_for_category?category_id={Uri.EscapeDataString(categoryId)}"; + + using var req = new HttpRequestMessage(HttpMethod.Get, url); + req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + req.Headers.Add("X-EBAY-C-MARKETPLACE-ID", "EBAY_GB"); + + var res = await _http.SendAsync(req); + var json = await res.Content.ReadAsStringAsync(); + if (!res.IsSuccessStatusCode) return new(); + + var aspects = new List(); + var arr = JObject.Parse(json)["aspects"] as JArray; + if (arr == null) { _cache[categoryId] = aspects; return aspects; } + + foreach (var item in arr) + { + var constraint = item["aspectConstraint"]; + if (constraint == null) continue; + + var required = constraint["aspectRequired"]?.Value() ?? false; + var usage = constraint["aspectUsage"]?.ToString() ?? ""; + if (!required && usage != "RECOMMENDED") continue; + + var aspect = new CategoryAspect + { + Name = item["localizedAspectName"]?.ToString() ?? "", + IsRequired = required, + IsFreeText = constraint["aspectMode"]?.ToString() != "SELECTION_ONLY" + }; + + var values = item["aspectValues"] as JArray; + if (values != null) + aspect.AllowedValues = values + .Select(v => v["localizedValue"]?.ToString() ?? "") + .Where(v => !string.IsNullOrEmpty(v)) + .Take(50) + .ToList(); + + if (!string.IsNullOrEmpty(aspect.Name)) + aspects.Add(aspect); + } + + _cache[categoryId] = aspects; + return aspects; + } +}