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 System.Net.Sockets; using System.Xml.Linq; using Pilz.Networking.CloudProviders.Nextcloud.Client.Cloud; using Pilz.Networking.CloudProviders.Nextcloud.Client.Core; using Pilz.Networking.CloudProviders.Nextcloud.Client.LoginFlowV2; using Pilz.Networking.CloudProviders.Nextcloud.Ocs.Responses; 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; } /// /// Makes an request with the given arguments and deserialize it to the given type. /// /// /// /// /// /// /// /// Returns the given OcsResponse type from the deserialized OcsApiResponse content. public TResponse? MakeRequestOcs(HttpMethod httpMethod, OcsApiUrlPath url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) where TResponse : IOcsResponse { return MakeRequestOcs(httpMethod, BuildFullUrl(url), useAuthentication: useAuthentication, parameters: parameters, content: content); } /// /// Makes an request with the given arguments and deserialize it to the given type. /// /// /// /// /// /// /// /// Returns the given OcsResponse type from the deserialized OcsApiResponse content. public TResponse? MakeRequestOcs(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) where TResponse : IOcsResponse { var response = MakeRequest?>(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content); if (response != null) return response.Ocs; return default; } /// /// Makes an request with the given arguments and deserialize it to the given type. /// /// /// /// /// /// /// /// Returns the deserialized content of type given type. public TResponse? 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); } /// /// Makes an request with the given arguments and deserialize it to the given type. /// /// /// /// /// /// /// /// Returns the deserialized content of type given type. public TResponse? MakeRequest(HttpMethod httpMethod, string url, bool useAuthentication = true, Dictionary? parameters = null, object? content = null) { using var responseInit = MakeRequest(httpMethod, url, useAuthentication: useAuthentication, parameters: parameters, content: content); if (responseInit != null) { try { var bodyInit = responseInit.Content.ReadAsStringAsync().Result; return JsonConvert.DeserializeObject(bodyInit); } catch(FormatException) { } catch(JsonSerializationException) { } } return default; } /// /// Makes an request with the given arguments. /// /// /// /// /// /// /// Returns a HttpResponseMessage as result. public HttpResponseMessage 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); } /// /// Makes an request with the given arguments. /// /// /// /// /// /// /// Returns a HttpResponseMessage as result. public HttpResponseMessage 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 || content is not null) { var stringContent = JsonConvert.SerializeObject(content); httpContent = new StringContent(stringContent, 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 }; // Add authorization if (authentication != null) request.Headers.Add("Authorization", authentication.ToBasicAuth()); return client.Send(request); } public void Dispose() { client.Dispose(); GC.SuppressFinalize(this); } } }