using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Http.Headers; using Newtonsoft.Json; using System.Diagnostics; using System.Net; using Pilz.Networking.CloudProviders.Nextcloud.OCS.APIs; using System.Net.Sockets; using Pilz.Networking.CloudProviders.Nextcloud.OCS.Data; namespace Pilz.Networking.CloudProviders.Nextcloud.OCS { public class OcsApi : IDisposable { public const string CONTENT_TYPE_JSON = "application/json"; public event GetOcsApiAuthCredentailsEventHandler? GetOcsApiAuthCredentails; private readonly HttpClient client = new(); private readonly List apis = new(); public string BaseUrl { get; set; } = string.Empty; public OcsApiLoginFlowV2 LoginFlowV2 => GetApi(); public OcsApiCore Core => GetApi(); public OcsApiCloud Cloud => GetApi(); public TApi GetApi() where TApi : OcsApiBase { var instance = TryGetApi(); return instance is null ? throw new NullReferenceException() : instance; } public TApi? TryGetApi() where TApi : OcsApiBase { TApi? instance = (TApi?)apis.FirstOrDefault(n => n is TApi); instance ??= (TApi?)Activator.CreateInstance(typeof(TApi), new object[] { this }); if (instance is not null) apis.Add(instance); return instance; } public string BuildFullUrl(OcsApiUrlPath path) { return BaseUrl + path; } public Task MakeRequest(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) { return MakeRequest(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content); } public Task MakeRequest(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) { return MakeRequest(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content); } public async Task MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) { using var responseInit = await MakeRequest(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content); if (responseInit != null) { var bodyInit = await responseInit.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject(bodyInit); } return default; } public async Task MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) { OcsApiAuthCredentials? authentication; string @params; HttpContent? httpContent; // Get authentication if (useAuthentication) { var args = new GetOcsApiAuthCredentailsEventArgs(); GetOcsApiAuthCredentails?.Invoke(this, args); authentication = args.Credentials; } else authentication = null; // Parse params if (parameters != null) @params = "?" + string.Join("&", parameters.Select(p => $"{p.Key}={p.Value}")); else @params = string.Empty; // Create content if (content is HttpContent contentHttp) httpContent = contentHttp; else if (content is OcsData) httpContent = new StringContent(JsonConvert.SerializeObject(content), null, CONTENT_TYPE_JSON); else httpContent = null; // Send request var request = new HttpRequestMessage { Method = httpMethod ?? HttpMethod.Post, RequestUri = new Uri(url + @params), Headers = { { "Accept", CONTENT_TYPE_JSON }, { "OCS-APIREQUEST", "true" }, { "Authorization", authentication.ToBasicAuth() } }, Content = httpContent }; return await client.SendAsync(request); } public void Dispose() { client.Dispose(); GC.SuppressFinalize(this); } } }