using System.Text; using PrismaticSync.Infrastructure; namespace PrismaticSync.Services; /// /// Pushes the scraped JSON to the app's token-authenticated catalog import endpoint. When no /// endpoint is configured it no-ops (the JSON is still on disk for a manual upload), so the tool is /// useful before the endpoint exists. /// public class CatalogPusher { private readonly SyncConfig _config; public CatalogPusher(SyncConfig config) => _config = config; public async Task PushAsync() { if (string.IsNullOrWhiteSpace(_config.Import.EndpointUrl)) { Log.Warn($"No import endpoint configured (Sync.Import.EndpointUrl) — skipping push. " + $"Upload {_config.OutputJsonFile} manually via the Powder Catalog admin instead."); return false; } if (!File.Exists(_config.OutputJsonFile)) { Log.Warn($"Output file {_config.OutputJsonFile} not found — nothing to push."); return false; } var json = await File.ReadAllTextAsync(_config.OutputJsonFile); Log.Info($"Pushing {_config.OutputJsonFile} to {_config.Import.EndpointUrl} (vendor: {_config.Import.VendorName})..."); using var http = new HttpClient { Timeout = TimeSpan.FromMinutes(5) }; using var request = new HttpRequestMessage(HttpMethod.Post, _config.Import.EndpointUrl); request.Headers.Add("X-Import-Token", _config.Import.Token); request.Headers.Add("X-Vendor-Name", _config.Import.VendorName); request.Content = new StringContent(json, Encoding.UTF8, "application/json"); try { using var response = await http.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { Log.Info($"Push succeeded ({(int)response.StatusCode}): {Trim(body)}"); return true; } Log.Error($"Push failed ({(int)response.StatusCode}): {Trim(body)}"); return false; } catch (Exception ex) { Log.Error($"Push error: {ex.Message}"); return false; } } private static string Trim(string s) => s.Length > 500 ? s[..500] + "…" : s; }