using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net.Http; using System.Threading.Tasks; using HtmlAgilityPack; using Markdig; using Octokit; using Ombi.Api; using Ombi.Api.Service; using Ombi.Core.Processor; using Ombi.Helpers; namespace Ombi.Schedule.Processor { public class ChangeLogProcessor : IChangeLogProcessor { public ChangeLogProcessor(IApi api, IOmbiHttpClient client) { _api = api; _client = client; } private readonly IApi _api; private readonly IOmbiHttpClient _client; private const string _changeLogUrl = "https://raw.githubusercontent.com/tidusjar/Ombi/{0}/CHANGELOG.md"; private const string AppveyorApiUrl = "https://ci.appveyor.com/api"; private string ChangeLogUrl(string branch) => string.Format(_changeLogUrl, branch); public async Task Process(string branch) { var masterBranch = branch.Equals("master", StringComparison.CurrentCultureIgnoreCase); string githubChangeLog; githubChangeLog = await _client.GetStringAsync(new Uri(ChangeLogUrl(branch))); var html = Markdown.ToHtml(githubChangeLog); var doc = new HtmlDocument(); doc.LoadHtml(html); HtmlNode latestRelease; if (masterBranch) { latestRelease = doc.DocumentNode.Descendants("h2") .FirstOrDefault(x => x.InnerText != "(unreleased)"); } else { latestRelease = doc.DocumentNode.Descendants("h2") .FirstOrDefault(x => x.InnerText == "(unreleased)"); if (latestRelease == null) { latestRelease = doc.DocumentNode.Descendants("h2") .FirstOrDefault(x => x.InnerText != "(unreleased)"); } } var newFeatureList = latestRelease.NextSibling.NextSibling.NextSibling.NextSibling; var featuresString = newFeatureList.ChildNodes.Where(x => x.Name != "#text").Select(x => x.InnerText.Replace("\\n", "")).ToList(); var fixes = newFeatureList.NextSibling.NextSibling.NextSibling.NextSibling; var fixesString = fixes.ChildNodes.Where(x => x.Name != "#text").Select(x => x.InnerText.Replace("\\n", "")).ToList(); // Cleanup var featuresList = featuresString.Distinct().ToList(); var fixesList = fixesString.Distinct().ToList(); // Get release var release = new Release { Version = latestRelease.InnerText, Features = featuresList, Fixes = fixesList, Downloads = new List() }; if (masterBranch) { var releaseTag = latestRelease.InnerText.Substring(0, 9); await GetGitubRelease(release, releaseTag); } else { // Get AppVeyor await GetAppVeyorRelease(release, branch); } return TransformUpdate(release); } private UpdateModel TransformUpdate(Release release) { var newUpdate = new UpdateModel { UpdateVersionString = release.Version.Substring(1,8), UpdateVersion = release.Version == "(unreleased)" ? 0 : int.Parse(release.Version.Substring(1, 5).Replace(".", "")), UpdateDate = DateTime.Now, ChangeLogs = new List(), Downloads = new List() }; foreach (var dl in release.Downloads) { newUpdate.Downloads.Add(new Downloads { Name = dl.Name, Url = dl.Url }); } foreach (var f in release.Features) { var change = new ChangeLog { Descripion = f, Type = "New", }; newUpdate.ChangeLogs.Add(change); } foreach (var f in release.Fixes) { var change = new ChangeLog { Descripion = f, Type = "Fixed", }; newUpdate.ChangeLogs.Add(change); } return newUpdate; } private async Task GetAppVeyorRelease(Release release, string branch) { var request = new Request($"/projects/tidusjar/requestplex/branch/{branch}", AppVeyorApi.AppveyorApiUrl, HttpMethod.Get); request.ApplicationJsonContentType(); var builds = await _api.Request(request); var jobId = builds.build.jobs.FirstOrDefault()?.jobId ?? string.Empty; if (builds.build.finished == DateTime.MinValue || builds.build.status.Equals("failed")) { return; } release.Version = builds.build.version; // get the artifacts request = new Request($"/buildjobs/{jobId}/artifacts", AppVeyorApi.AppveyorApiUrl, HttpMethod.Get); request.ApplicationJsonContentType(); var artifacts = await _api.Request>(request); foreach (var item in artifacts) { var d = new Downloads { Name = item.fileName, Url = $"{AppveyorApiUrl}/buildjobs/{jobId}/artifacts/{item.fileName}" }; release.Downloads.Add(d); } } private async Task GetGitubRelease(Release release, string releaseTag) { var client = new GitHubClient(Octokit.ProductHeaderValue.Parse("OmbiV3")); var releases = await client.Repository.Release.GetAll("tidusjar", "ombi"); var latest = releases.FirstOrDefault(x => x.TagName == releaseTag); if (latest.Name.Contains("V2", CompareOptions.IgnoreCase)) { latest = null; } if (latest == null) { latest = releases.OrderByDescending(x => x.CreatedAt).FirstOrDefault(); } foreach (var item in latest.Assets) { var d = new Downloads { Name = item.Name, Url = item.BrowserDownloadUrl }; release.Downloads.Add(d); } } } public class Release { public string Version { get; set; } public string CheckinVersion { get; set; } public List Downloads { get; set; } public List Features { get; set; } public List Fixes { get; set; } } public class Downloads { public string Name { get; set; } public string Url { get; set; } } }