using Newtonsoft.Json; using Publisher.Models; using Publisher.Models.Confluence; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Publisher.Services { public class Confluence { private string Username; private string Password; private string Host; public delegate void StatusUpdateHandler(object sender, StatusUpdateArgs e); public event StatusUpdateHandler OnUpdateStatus; public Confluence(string host, string username, string password) { this.Host = host; this.Username = username; this.Password = password; } public bool DeletePage(int pageId) { bool result = false; try { string auth = this.GetAuth(); if (!string.IsNullOrEmpty(this.Host) && !string.IsNullOrEmpty(auth) && pageId > 0) { string url = this.Host + "/rest/api/content/" + pageId.ToString(); HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Method = "DELETE"; webRequest.Headers.Add("Authorization", auth); webRequest.ContentType = "application/json; charset=utf-8"; webRequest.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse(); result = response.StatusCode == HttpStatusCode.NoContent; } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } return result; } public ResponsePage UpdatePage(string title, string spaceKey, string pageId, string bodyHTML) { ResponsePage result = null; try { string auth = this.GetAuth(); if (!string.IsNullOrEmpty(this.Host) && !string.IsNullOrEmpty(auth) && !string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(pageId)) { string url = this.Host + "/rest/api/content/" + pageId.ToString(); HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Method = "PUT"; webRequest.Headers.Add("Authorization", auth); webRequest.ContentType = "application/json; charset=utf-8"; webRequest.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; using (Stream stream = webRequest.GetRequestStream()) { Content content = new Content(); content.title = title; content.version = new ContentVersion(); content.version.number = 2; content.id = pageId; if (!string.IsNullOrEmpty(spaceKey)) { content.space = new Space(); content.space.key = spaceKey; } content.body = new Body(); content.body.storage = new Storage(); content.body.storage.value = bodyHTML; string dataJSON = JsonConvert.SerializeObject(content); byte[] data = Encoding.UTF8.GetBytes(dataJSON); stream.Write(data, 0, data.Length); } WebResponse response = (HttpWebResponse)webRequest.GetResponse(); string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); if (!string.IsNullOrEmpty(json)) { try { result = JsonConvert.DeserializeObject(json); } catch (Exception ex) { try { Response res = JsonConvert.DeserializeObject(json); if (res != null) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", res.reason)); } } } catch (Exception ex1) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } } } } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } return result; } public void DeleteOldChildPages(int parentPageId, int limit = 5) { try { string auth = this.GetAuth(); Models.Confluence.Page[] childPages = this.GetChildPages(parentPageId); if (childPages != null && childPages.Length > 0) { List sortChildPages = new List(childPages); sortChildPages = sortChildPages.OrderByDescending(m => m.id).ToList(); for(int i = 0; i < sortChildPages.Count; i++) { if(i >= limit) { this.DeletePage(sortChildPages[i].id); Thread.Sleep(1000); } } } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } } public Models.Confluence.Page[] GetChildPages(int parentPageId) { Models.Confluence.Page[] result = null; try { string auth = this.GetAuth(); if (!string.IsNullOrEmpty(this.Host) && !string.IsNullOrEmpty(auth)) { string url = this.Host + "/rest/api/content/" + parentPageId.ToString() + "/child/page"; HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Method = "GET"; webRequest.Headers.Add("Authorization", auth); webRequest.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; WebResponse response = (HttpWebResponse)webRequest.GetResponse(); string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); if (!string.IsNullOrEmpty(json)) { SearchResults searchResults = JsonConvert.DeserializeObject(json); if (searchResults != null && searchResults.results != null && searchResults.results.Length > 0) { result = searchResults.results; } } } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } return result; } public ResponsePage CreatePage(string title, string spaceKey, string bodyHTML, int? parentPageId = null) { ResponsePage result = null; try { string auth = this.GetAuth(); if (!string.IsNullOrEmpty(this.Host) && !string.IsNullOrEmpty(auth) && !string.IsNullOrEmpty(title)) { string url = this.Host + "/rest/api/content/"; HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Method = "POST"; webRequest.Headers.Add("Authorization", auth); webRequest.ContentType = "application/json; charset=utf-8"; webRequest.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; using (Stream stream = webRequest.GetRequestStream()) { Content content = new Content(); content.title = title; if(!string.IsNullOrEmpty(spaceKey)) { content.space = new Space(); content.space.key = spaceKey; } if(parentPageId.HasValue) { content.ancestors = new Ancestors[] { new Ancestors() { id = parentPageId.Value } }; } content.body = new Body(); content.body.storage = new Storage(); content.body.storage.value = bodyHTML; string dataJSON = JsonConvert.SerializeObject(content); byte[] data = Encoding.UTF8.GetBytes(dataJSON); stream.Write(data, 0, data.Length); } WebResponse response = (HttpWebResponse)webRequest.GetResponse(); string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); if (!string.IsNullOrEmpty(json)) { try { result = JsonConvert.DeserializeObject(json); } catch (Exception ex) { try { Response res = JsonConvert.DeserializeObject(json); if(res != null) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", res.reason)); } } } catch (Exception ex1) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } } } } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } return result; } public ResponseAttachment AddAttachment(string pageId, string file, string content_type, string comment = null) { ResponseAttachment result = null; try { string auth = this.GetAuth(); if (!string.IsNullOrEmpty(this.Host) && !string.IsNullOrEmpty(auth) && !string.IsNullOrEmpty(file) && File.Exists(file)) { string url = this.Host + "/rest/api/content/" + pageId.ToString() + "/child/attachment"; HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.CookieContainer = new CookieContainer(); webRequest.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x"); webRequest.ContentType = "multipart/form-data; boundary=" + boundary; webRequest.Method = "POST"; webRequest.Headers.Add("Authorization", auth); webRequest.Headers.Add("X-Atlassian-Token", "no-check"); boundary = "--" + boundary; using (Stream stream = webRequest.GetRequestStream()) { if(!string.IsNullOrEmpty(comment)) { byte[] comment_bytes = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); stream.Write(comment_bytes, 0, comment_bytes.Length); comment_bytes = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", "comment", Environment.NewLine)); stream.Write(comment_bytes, 0, comment_bytes.Length); comment_bytes = Encoding.UTF8.GetBytes(comment + Environment.NewLine); stream.Write(comment_bytes, 0, comment_bytes.Length); } // Write the files var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine); stream.Write(buffer, 0, buffer.Length); buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", "file", Path.GetFileName(file), Environment.NewLine)); stream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", content_type, Environment.NewLine)); stream.Write(buffer, 0, buffer.Length); byte[] file_bytes = File.ReadAllBytes(file); stream.Write(file_bytes, 0, file_bytes.Length); buffer = Encoding.ASCII.GetBytes(Environment.NewLine); stream.Write(buffer, 0, buffer.Length); byte[] boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--"); stream.Write(boundaryBuffer, 0, boundaryBuffer.Length); } WebResponse response = (HttpWebResponse)webRequest.GetResponse(); string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); if (!string.IsNullOrEmpty(json)) { ResponseAttachments attachments = JsonConvert.DeserializeObject(json); if(attachments != null && attachments.results != null && attachments.results.Length > 0) { result = attachments.results[0]; } } } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } return result; } public Page[] SearchPages(string title = null, string spaceKey = null) { Models.Confluence.Page[] result = null; try { string auth = this.GetAuth(); if(!string.IsNullOrEmpty(this.Host) && !string.IsNullOrEmpty(auth)) { string param = null; if(!string.IsNullOrEmpty(title)) { param = "title=" + title; } if (!string.IsNullOrEmpty(spaceKey)) { if(!string.IsNullOrEmpty(param)) { param = param + "&spaceKey=" + spaceKey; } else { param = "spaceKey=" + spaceKey; } } string url = this.Host + "/rest/api/content/" + (!string.IsNullOrEmpty(param) ? "?" + param : ""); HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Method = "GET"; webRequest.Headers.Add("Authorization", auth); webRequest.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }; WebResponse response = (HttpWebResponse)webRequest.GetResponse(); string json = new StreamReader(response.GetResponseStream()).ReadToEnd(); if(!string.IsNullOrEmpty(json)) { SearchResults searchResults = JsonConvert.DeserializeObject(json); if(searchResults != null && searchResults.results != null && searchResults.results.Length > 0) { result = searchResults.results; } } } } catch (Exception ex) { if (OnUpdateStatus != null) { OnUpdateStatus(this, new StatusUpdateArgs("Error", ex.Message)); } } return result; } private string GetAuth() { string result = null; if(!string.IsNullOrEmpty(this.Username) && !string.IsNullOrEmpty(this.Password)) { result = "Basic " + System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(this.Username + ":" + this.Password)); } return result; } } }