using Newtonsoft.Json; using paperless_ngx_export.Models; using System; using System.Collections.Generic; using System.Net.Http.Headers; using System.Text; using System.Text.Json.Nodes; namespace paperless_ngx_export { public static class api { public static bool isInitialized { get; private set; } = false; static string paperless_api_base; static string token; public static void init(string token, string paperless_api_base) { api.paperless_api_base = paperless_api_base.Trim(); setToken(token.Trim()); isInitialized = !string.IsNullOrWhiteSpace(api.paperless_api_base) && !string.IsNullOrEmpty(api.token); } private static void setToken(string token) { api.token = token.Trim().Trim('/'); } private static HttpRequestMessage getHttpRequestMessage(string query, int page = -1) { if (page > 0) { var pagedQuery = query.Contains('?') ? $"{query}&page={page}" : $"{query}?page={page}"; return getHttpRequestMessage(pagedQuery, HttpMethod.Get); } else return getHttpRequestMessage(query, HttpMethod.Get); } private static HttpRequestMessage getHttpRequestMessage(string query, HttpMethod httpMethod) { HttpRequestMessage message = new HttpRequestMessage(httpMethod, $"{api.paperless_api_base}{query}"); //message.Headers.Authorization = getAuthenticationHeaderValue(); message.Headers.Add("Authorization", $"Token {api.token}"); return message; } private static AuthenticationHeaderValue getAuthenticationHeaderValue() { var header = new AuthenticationHeaderValue("Token", api.token); return header; } public static async Task> getTagsAsync() { var query = "tags/"; var tags = new List(); if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } using (HttpClient client = new HttpClient()) { var count = -1; var page = 1; while (count != 0) { count = 0; var response = await client.SendAsync(getHttpRequestMessage(query, page)); if (response != null && response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var root = JsonConvert.DeserializeObject>(responseString); if (root.Results.Any()) { count = root.Results.Count(); tags.AddRange(root.Results); } } page++; } } return tags; } public static async Task> getCurrentDocumentsAsync(bool includeNonExpirableDocuments = true) { var query = "documents/"; var excludedTagIds = (await getTagsAsync()).Where(x => (includeNonExpirableDocuments && x.name == "No Expiration") || x.name == "Action:Renewed" || x.name == "HR:Inactive").Select(x => x.Id).ToList(); excludedTagIds.ForEach(id => query += query.Contains('?') ? $"&tags__id__none={id}" : $"?tags__id__none={id}"); var documents = new List(); if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } using (HttpClient client = new HttpClient()) { var count = -1; var page = 1; while (count != 0) { count = 0; var response = await client.SendAsync(getHttpRequestMessage(query, page)); if (response != null && response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var root = JsonConvert.DeserializeObject>(responseString); if (root.Results.Any()) { count = root.Results.Count(); foreach (var document in root.Results) { bool isValid = true; foreach (var t in document.tags) if (excludedTagIds.Contains(t)) isValid = false; if(isValid) documents.Add(document); } } } page++; } } return documents.OrderBy(d=>d.correspondent).ToList(); } public static async Task> getAllDocumentsAsync() { var query = "documents/"; var documents = new List(); if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } using (HttpClient client = new HttpClient()) { var count = -1; var page = 1; while (count != 0) { count = 0; var response = await client.SendAsync(getHttpRequestMessage(query, page)); if (response != null && response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var root = JsonConvert.DeserializeObject>(responseString); if (root.Results.Any()) { count = root.Results.Count(); documents.AddRange(root.Results); } } page++; } } return documents; } public static async Task> getCorrespondentsAsync() { var query = "correspondents/"; if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } var correspondents = new List(); using (HttpClient client = new HttpClient()) { var count = -1; var page = 1; while (count != 0) { count = 0; var response = await client.SendAsync(getHttpRequestMessage(query, page)); if (response != null && response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var root = JsonConvert.DeserializeObject>(responseString); if (root.Results.Any()) { count = root.Results.Count(); correspondents.AddRange(root.Results); } } page++; } } return correspondents; } public static async Task> getCustomFieldsAsync() { var query = "custom_fields/"; var fields = new List(); if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } using (HttpClient client = new HttpClient()) { var count = -1; var page = 1; while (count != 0) { count = 0; var response = await client.SendAsync(getHttpRequestMessage(query, page)); if (response != null && response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var root = JsonConvert.DeserializeObject>(responseString); if (root.Results.Any()) { count = root.Results.Count(); fields.AddRange(root.Results); } } page++; } } return fields; } public static async Task> getDocumentTypesAsync() { var query = "document_types/"; var doctypes = new List(); if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } using (HttpClient client = new HttpClient()) { var count = -1; var page = 1; while (count != 0) { count = 0; var response = await client.SendAsync(getHttpRequestMessage(query, page)); if (response != null && response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); var root = JsonConvert.DeserializeObject>(responseString); if (root.Results.Any()) { count = root.Results.Count(); doctypes.AddRange(root.Results); } } page++; } } return doctypes; } public static async Task getExpirationDatesCalDAVAsync(bool onlyCurrentDocuments = true) { string caldav = @"BEGIN:VCALENDAR VERSION:2.0 PRODID:-//CAMCASS//Expiring Documents Calendar//EN X-WR-CALNAME:Expiring Documents X-WR-CALDESC:Onboarded staff's document expiration dates X-PUBLISHED-TTL:PT12H"; if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } var documents = (await getMergedDocumentMetadataAsync(onlyCurrentDocuments, false)).OrderBy(x=>x.Correspondent).ToList(); documents.Where(d => d.CustomFields.Any(f => f.Name.StartsWith("Expiration", StringComparison.OrdinalIgnoreCase))) .ToList() .ForEach(doc => { var calDAVEvent = getCalDAVEvent(doc, doc.CustomFields.First(f => f.Name.StartsWith("expir", StringComparison.OrdinalIgnoreCase)).DateValue); caldav += @$" {calDAVEvent}"; }); caldav += @" END:VCALENDAR"; return caldav; } private static string getCalDAVEvent(DocumentParsed document, DateTime date) { var nextDay = date.AddDays(1); var DTSTAMP = $"{DateTime.UtcNow.Year:0000}{DateTime.UtcNow.Month:00}{DateTime.UtcNow.Day:00}T{DateTime.UtcNow.Hour:00}{DateTime.UtcNow.Minute:00}00Z"; return $@"BEGIN:VEVENT UID:{Guid.NewGuid().ToString().Replace("-","")} DTSTAMP:{DTSTAMP} DTSTART;VALUE=DATE:{date.Year:0000}{date.Month:00}{date.Day:00} DTEND;VALUE=DATE:{nextDay.Year:0000}{nextDay.Month:00}{nextDay.Day:00} SUMMARY:{document.DocumentType} - {document.Correspondent} END:VEVENT"; } public static async Task> getMergedDocumentMetadataAsync(bool onlyCurrentDocuments = true, bool includeNonExpirableDocuments=true) { if (!isInitialized) { throw new NotSupportedException("API base URL or token not initialized"); } var docs = onlyCurrentDocuments ? await getCurrentDocumentsAsync(includeNonExpirableDocuments) : await getAllDocumentsAsync(); var tags = await getTagsAsync(); var correspondents = await getCorrespondentsAsync(); var customFields = await getCustomFieldsAsync(); var documenttypes = await getDocumentTypesAsync(); DocumentParsed._tags = tags.ToArray(); DocumentParsed._correspondents = correspondents.ToArray(); DocumentParsed._customFields = customFields.ToArray(); DocumentParsed._documentTypes = documenttypes.ToArray(); var documents = new List(); docs.ToList().ForEach(document => documents.Add(DocumentParsed.FromDocument(document))); return documents; } } }