using Cleanuparr.Shared.Helpers; namespace Cleanuparr.Infrastructure.Helpers; public class FileReader { private readonly HttpClient _httpClient; public FileReader(IHttpClientFactory httpClientFactory) { _httpClient = httpClientFactory.CreateClient(Constants.HttpClientWithRetryName); } /// /// Whether a configured path points at a remote URL rather than a file on disk. /// An absolute local path parses as a file:// URI, so the scheme has to be checked. /// public static bool IsRemote(string? path) => Uri.TryCreate(path, UriKind.Absolute, out Uri? uri) && (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps); /// /// Resolves a configured path to something the file system understands, unwrapping a file:// URI to the path it points at. /// public static string ToLocalPath(string path) => Uri.TryCreate(path, UriKind.Absolute, out Uri? uri) && uri.Scheme == Uri.UriSchemeFile ? uri.LocalPath : path; /// /// Reads content from either a local file or HTTP(S) URL /// Extracted from BlocklistProvider.ReadContentAsync for reuse /// /// File path or URL /// Array of lines from the content public async Task ReadContentAsync(string path) { if (IsRemote(path)) { return await ReadFromUrlAsync(path); } string localPath = ToLocalPath(path); if (File.Exists(localPath)) { return await File.ReadAllLinesAsync(localPath); } throw new ArgumentException($"File not found: {path}"); } private async Task ReadFromUrlAsync(string url) { using HttpResponseMessage response = await _httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); return (await response.Content.ReadAsStringAsync()) .Split(['\r','\n'], StringSplitOptions.RemoveEmptyEntries); } }