From 0b95530eed9a961fac304b1d4a148f6fe3b52169 Mon Sep 17 00:00:00 2001 From: stam Date: Wed, 20 Jan 2021 00:39:18 +0300 Subject: [PATCH] 1.0.0.7 * version page * code improvments --- src/DonloaderService.cs | 346 ++++++++++++++++++++------------ src/Models/DownloaderOptions.cs | 4 +- src/Models/ResponseItem.cs | 50 ++--- src/Program.cs | 9 +- src/atlassian-downloader.csproj | 3 +- 5 files changed, 256 insertions(+), 156 deletions(-) diff --git a/src/DonloaderService.cs b/src/DonloaderService.cs index 7555758..6b865ae 100644 --- a/src/DonloaderService.cs +++ b/src/DonloaderService.cs @@ -1,76 +1,179 @@ -using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using System; +using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Reflection; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + namespace EpicMorg.Atlassian.Downloader -{ +{ class DonloaderService : IHostedService - { - private readonly ILogger logger; + { + private readonly ILogger logger; private readonly DownloaderOptions options; private readonly HttpClient client; private readonly IHostApplicationLifetime hostApplicationLifetime; + private readonly string assemblyEnvironment = string.Format("[{1}, {0}]", + System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(), + System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription); + private readonly string assemblyVersion = Assembly.GetEntryAssembly().GetCustomAttribute().InformationalVersion; + + private readonly string assemblyName = Assembly.GetEntryAssembly().GetCustomAttribute().Product; + const string assemblyBuildType = +#if DEBUG + "[Debug]" +#else + + "[Release]" +#endif + ; public DonloaderService(IHostApplicationLifetime hostApplicationLifetime, ILogger logger, HttpClient client, DownloaderOptions options) - { - this.logger = logger; - this.client = client; + { + this.logger = logger; + this.client = client; this.options = options; this.hostApplicationLifetime = hostApplicationLifetime; } - - public async Task StartAsync(CancellationToken cancellationToken) - { - this.SetConsoleTitle(); - var feedUrls = this.GetFeedUrls(); - - logger.LogInformation($"Task started"); - foreach (var feedUrl in feedUrls) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - var (json, versions) = await this.GetJson(feedUrl, cancellationToken).ConfigureAwait(false); + public const ConsoleColor DEFAULT = ConsoleColor.Blue; - switch (options.Action) - { - case DownloadAction.ShowRawJson: - Console.Out.WriteLine(json); - break; - case DownloadAction.Download: - await this.DownloadFilesFromFreed(feedUrl, versions, cancellationToken).ConfigureAwait(false); - break; - case DownloadAction.ListURLs: - foreach (var versionProg in versions) - { - foreach (var file in versionProg.Value) + public static void WriteColorLine(string text, params object[] args) + { + Dictionary colors = new() + { + { '!', ConsoleColor.Red }, + { '@', ConsoleColor.Green }, + { '#', ConsoleColor.Blue }, + { '$', ConsoleColor.Magenta }, + { '&', ConsoleColor.Yellow }, + { '%', ConsoleColor.Cyan } + }; + // TODO: word wrap, backslash escapes + text = string.Format(text, args); + string chunk = ""; + bool paren = false; + for (int i = 0; i < text.Length; i++) + { + char c = text[i]; + if (colors.ContainsKey(c) && StringNext(text, i) != ' ') + { + Console.Write(chunk); + chunk = ""; + if (StringNext(text, i) == '(') + { + i++; // skip past the paren + paren = true; + } + Console.ForegroundColor = colors[c]; + } + else if (paren && c == ')') + { + paren = false; + Console.ForegroundColor = DEFAULT; + } + else if (Console.ForegroundColor != DEFAULT) + { + Console.Write(c); + if (c == ' ' && !paren) + Console.ForegroundColor = DEFAULT; + } + else + chunk += c; + } + Console.WriteLine(chunk); + Console.ForegroundColor = DEFAULT; + } + + public static char StringPrev(string text, int index) + { + return (index == 0 || text.Length == 0) ? '\0' : text[index - 1]; + } + + public static char StringNext(string text, int index) + { + return (index < text.Length) ? text[index + 1] : '\0'; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + SetConsoleTitle(); + if (options.Version) + { + logger.LogInformation($"{assemblyName} {assemblyVersion} {assemblyEnvironment} {assemblyBuildType}"); + Console.BackgroundColor = ConsoleColor.Black; + WriteColorLine("%╔═╦═══════════════════════════════════════════════════════════════════════════════════════╦═╗"); + WriteColorLine("%╠═╝ .''. %╚═%╣"); + WriteColorLine("%║ .:cc;. %║"); + WriteColorLine("%║ .;cccc;. %║"); + WriteColorLine("%║ .;cccccc;. !╔══════════════════════════════════════════════╗ %║"); + WriteColorLine("%║ .:ccccccc;. !║ "+ assemblyName +" !║ %║"); + WriteColorLine("%║ 'ccccccccc;. !╠══════════════════════════════════════════════╣ %║"); + WriteColorLine("%║ ,cccccccccc;. !║ &Code: @kastkack !║ %║"); + WriteColorLine("%║ ,ccccccccccc;. !║ &GFX: @stam !║ %║"); + WriteColorLine("%║ .... .:ccccccccccc;. !╠══════════════════════════════════════════════╣ %║"); + WriteColorLine("%║ .',,'..;cccccccccccc;. !║ &Version: "+ assemblyVersion + " !║ %║"); + WriteColorLine("%║ .,,,,,'.';cccccccccccc;. !║ &GitHub: $EpicMorg/atlassian-downloader !║ %║"); + WriteColorLine("%║ .,;;;;;,'.':cccccccccccc;. !╚══════════════════════════════════════════════╝ %║"); + WriteColorLine("%║ .;:;;;;;;,...:cccccccccccc;. %║"); + WriteColorLine("%║ .;:::::;;;;'. .;:ccccccccccc;. %║"); + WriteColorLine("%║ .:cc::::::::,. ..:ccccccccccc;. %║"); + WriteColorLine("%║ .:cccccc:::::' .:ccccccccccc;. %║"); + WriteColorLine("%║ .;:::::::::::,. .;:::::::::::,. %║"); + WriteColorLine("%╠═╗ ............ ............ %╔═╣"); + WriteColorLine("%╚═╩═══════════════════════════════════════════════════════════════════════════════════════╩═╝"); + Console.ResetColor(); + } + else + { + var feedUrls = this.GetFeedUrls(); + + logger.LogInformation($"Task started"); + foreach (var feedUrl in feedUrls) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + var (json, versions) = await this.GetJson(feedUrl, cancellationToken).ConfigureAwait(false); + + switch (options.Action) + { + case DownloadAction.ShowRawJson: + Console.Out.WriteLine(json); + break; + case DownloadAction.Download: + await this.DownloadFilesFromFreed(feedUrl, versions, cancellationToken).ConfigureAwait(false); + break; + case DownloadAction.ListURLs: + foreach (var versionProg in versions) { - Console.Out.WriteLine(file.ZipUrl); + foreach (var file in versionProg.Value) + { + Console.Out.WriteLine(file.ZipUrl); + } } - } - break; - case DownloadAction.ListVersions: - foreach (var versionProg in versions) - { - foreach (var file in versionProg.Value) + break; + case DownloadAction.ListVersions: + foreach (var versionProg in versions) { - Console.Out.WriteLine(file.Version); + foreach (var file in versionProg.Value) + { + Console.Out.WriteLine(file.Version); + } } - } - break; - } - } - logger.LogInformation($"Complete"); - this.hostApplicationLifetime.StopApplication(); + break; + } + } + } + logger.LogInformation($"Complete"); + + this.hostApplicationLifetime.StopApplication(); } private async Task<(string json, IDictionary versions)> GetJson(string feedUrl, CancellationToken cancellationToken) @@ -88,94 +191,87 @@ namespace EpicMorg.Atlassian.Downloader private string[] GetFeedUrls() => options.CustomFeed != null ? options.CustomFeed.Select(a => a.ToString()).ToArray() - : new[] { + : new[] { "https://my.atlassian.com/download/feeds/archived/bamboo.json", - "https://my.atlassian.com/download/feeds/archived/clover.json", - "https://my.atlassian.com/download/feeds/archived/confluence.json", - "https://my.atlassian.com/download/feeds/archived/crowd.json", - "https://my.atlassian.com/download/feeds/archived/crucible.json", - "https://my.atlassian.com/download/feeds/archived/fisheye.json", - "https://my.atlassian.com/download/feeds/archived/jira-core.json", - "https://my.atlassian.com/download/feeds/archived/jira-servicedesk.json", - "https://my.atlassian.com/download/feeds/archived/jira-software.json", - "https://my.atlassian.com/download/feeds/archived/jira.json", - "https://my.atlassian.com/download/feeds/archived/stash.json", - + "https://my.atlassian.com/download/feeds/archived/clover.json", + "https://my.atlassian.com/download/feeds/archived/confluence.json", + "https://my.atlassian.com/download/feeds/archived/crowd.json", + "https://my.atlassian.com/download/feeds/archived/crucible.json", + "https://my.atlassian.com/download/feeds/archived/fisheye.json", + "https://my.atlassian.com/download/feeds/archived/jira-core.json", + "https://my.atlassian.com/download/feeds/archived/jira-servicedesk.json", + "https://my.atlassian.com/download/feeds/archived/jira-software.json", + "https://my.atlassian.com/download/feeds/archived/jira.json", + "https://my.atlassian.com/download/feeds/archived/stash.json", + "https://my.atlassian.com/download/feeds/current/bamboo.json", - "https://my.atlassian.com/download/feeds/current/clover.json", - "https://my.atlassian.com/download/feeds/current/confluence.json", - "https://my.atlassian.com/download/feeds/current/crowd.json", - "https://my.atlassian.com/download/feeds/current/crucible.json", - "https://my.atlassian.com/download/feeds/current/fisheye.json", - "https://my.atlassian.com/download/feeds/current/jira-core.json", - "https://my.atlassian.com/download/feeds/current/jira-servicedesk.json", - "https://my.atlassian.com/download/feeds/current/jira-software.json", - "https://my.atlassian.com/download/feeds/current/stash.json", - - "https://my.atlassian.com/download/feeds/eap/bamboo.json", - "https://my.atlassian.com/download/feeds/eap/confluence.json", - "https://my.atlassian.com/download/feeds/eap/jira.json", + "https://my.atlassian.com/download/feeds/current/clover.json", + "https://my.atlassian.com/download/feeds/current/confluence.json", + "https://my.atlassian.com/download/feeds/current/crowd.json", + "https://my.atlassian.com/download/feeds/current/crucible.json", + "https://my.atlassian.com/download/feeds/current/fisheye.json", + "https://my.atlassian.com/download/feeds/current/jira-core.json", + "https://my.atlassian.com/download/feeds/current/jira-servicedesk.json", + "https://my.atlassian.com/download/feeds/current/jira-software.json", + "https://my.atlassian.com/download/feeds/current/stash.json", + + "https://my.atlassian.com/download/feeds/eap/bamboo.json", + "https://my.atlassian.com/download/feeds/eap/confluence.json", + "https://my.atlassian.com/download/feeds/eap/jira.json", "https://my.atlassian.com/download/feeds/eap/jira-servicedesk.json", - "https://my.atlassian.com/download/feeds/eap/stash.json", - - //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json", - - //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json - "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json" + "https://my.atlassian.com/download/feeds/eap/stash.json", + + //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/archived/sourcetree.json", + + //https://raw.githubusercontent.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json + "https://raw.githack.com/EpicMorg/atlassian-json/master/json-backups/current/sourcetree.json" }; - private void SetConsoleTitle() - { - const string appBuildType = -#if DEBUG - "[Debug]" -#else - - "[Release]" -#endif - ; - var assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName(); - Console.Title = $@"{assemblyName.Name} {assemblyName.Version} {appBuildType}"; + private void SetConsoleTitle() + { + Console.Title = $@"{assemblyName} {assemblyVersion} {assemblyEnvironment} - {assemblyBuildType}"; } private async Task DownloadFilesFromFreed(string feedUrl, IDictionary versions, CancellationToken cancellationToken) { - var feedDir = Path.Combine(options.OutputDir, feedUrl[(feedUrl.LastIndexOf('/') + 1)..(feedUrl.LastIndexOf('.'))]); - logger.LogInformation($"Download from JSON \"{feedUrl}\" started"); - foreach (var version in versions) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var directory = Path.Combine(feedDir, version.Key); - if (!Directory.Exists(directory)) - { - Directory.CreateDirectory(directory); - } - foreach (var file in version.Value) + + var feedDir = Path.Combine(options.OutputDir, feedUrl[(feedUrl.LastIndexOf('/') + 1)..(feedUrl.LastIndexOf('.'))]); + logger.LogInformation($"Download from JSON \"{feedUrl}\" started"); + foreach (var version in versions) { if (cancellationToken.IsCancellationRequested) { return; } - if (file.ZipUrl == null) { continue; } - var serverPath = file.ZipUrl.PathAndQuery; - var outputFile = Path.Combine(directory, serverPath[(serverPath.LastIndexOf("/") + 1)..]); - if (!File.Exists(outputFile)) + + var directory = Path.Combine(feedDir, version.Key); + if (!Directory.Exists(directory)) { - await DownloadFile(file, outputFile, cancellationToken).ConfigureAwait(false); + Directory.CreateDirectory(directory); } - else + foreach (var file in version.Value) { - logger.LogWarning($"File \"{outputFile}\" already exists. Download from \"{file.ZipUrl}\" skipped."); + if (cancellationToken.IsCancellationRequested) + { + return; + } + if (file.ZipUrl == null) { continue; } + var serverPath = file.ZipUrl.PathAndQuery; + var outputFile = Path.Combine(directory, serverPath[(serverPath.LastIndexOf("/") + 1)..]); + if (!File.Exists(outputFile)) + { + await DownloadFile(file, outputFile, cancellationToken).ConfigureAwait(false); + } + else + { + logger.LogWarning($"File \"{outputFile}\" already exists. Download from \"{file.ZipUrl}\" skipped."); + } } } - } - logger.LogInformation($"All files from \"{feedUrl}\" successfully downloaded."); + logger.LogInformation($"All files from \"{feedUrl}\" successfully downloaded."); + } private async Task DownloadFile(ResponseItem file, string outputFile, CancellationToken cancellationToken) @@ -205,6 +301,8 @@ namespace EpicMorg.Atlassian.Downloader logger.LogInformation($"File \"{file.ZipUrl}\" successfully downloaded to \"{outputFile}\"."); } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task StopAsync(CancellationToken cancellationToken) { } - } +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + } } \ No newline at end of file diff --git a/src/Models/DownloaderOptions.cs b/src/Models/DownloaderOptions.cs index ea43012..aca9cb8 100644 --- a/src/Models/DownloaderOptions.cs +++ b/src/Models/DownloaderOptions.cs @@ -1,6 +1,6 @@ using System; namespace EpicMorg.Atlassian.Downloader -{ - public record DownloaderOptions(string OutputDir, Uri[] CustomFeed, DownloadAction Action) { } +{ + public record DownloaderOptions(string OutputDir, Uri[] CustomFeed, DownloadAction Action,bool Version) { } } \ No newline at end of file diff --git a/src/Models/ResponseItem.cs b/src/Models/ResponseItem.cs index 939a3da..ce4e66e 100644 --- a/src/Models/ResponseItem.cs +++ b/src/Models/ResponseItem.cs @@ -1,31 +1,31 @@ -using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using System; +using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + namespace EpicMorg.Atlassian.Downloader -{ - +{ + public partial class ResponseItem - { - public string Description { get; set; } - public string Edition { get; set; } - public Uri ZipUrl { get; set; } - public object TarUrl { get; set; } - public string Md5 { get; set; } - public string Size { get; set; } - public string Released { get; set; } - public string Type { get; set; } - public string Platform { get; set; } - public string Version { get; set; } - public Uri ReleaseNotes { get; set; } - public Uri UpgradeNotes { get; set; } - } + { + public string Description { get; set; } + public string Edition { get; set; } + public Uri ZipUrl { get; set; } + public object TarUrl { get; set; } + public string Md5 { get; set; } + public string Size { get; set; } + public string Released { get; set; } + public string Type { get; set; } + public string Platform { get; set; } + public string Version { get; set; } + public Uri ReleaseNotes { get; set; } + public Uri UpgradeNotes { get; set; } + } } \ No newline at end of file diff --git a/src/Program.cs b/src/Program.cs index a956fbb..58fff86 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -16,9 +16,10 @@ namespace EpicMorg.Atlassian.Downloader /// Atlassian archive downloader. See https://github.com/EpicMorg/atlassian-downloader for more info /// /// Action to perform - /// Override output directory to download. - /// Override URIs to import. - static async Task Main(string OutputDir = "atlassian", Uri[] customFeed = null, DownloadAction Action = DownloadAction.Download) => await + /// Override output directory to download + /// Override URIs to import + /// Show credits" banner + static async Task Main(string OutputDir = "atlassian", Uri[] customFeed = null, DownloadAction Action = DownloadAction.Download, bool Version = false) => await Host .CreateDefaultBuilder() .ConfigureHostConfiguration(configHost => configHost.AddEnvironmentVariables()) @@ -40,7 +41,7 @@ namespace EpicMorg.Atlassian.Downloader .AddSerilog(dispose: true); }) .AddHostedService() - .AddSingleton(new DownloaderOptions(OutputDir, customFeed, Action)) + .AddSingleton(new DownloaderOptions(OutputDir, customFeed, Action, Version)) .AddHttpClient()) .RunConsoleAsync() .ConfigureAwait(false); diff --git a/src/atlassian-downloader.csproj b/src/atlassian-downloader.csproj index af77227..0c606eb 100644 --- a/src/atlassian-downloader.csproj +++ b/src/atlassian-downloader.csproj @@ -10,7 +10,7 @@ net5.0 favicon.ico EpicMorg.Atlassian.Downloader - Atlassian Downloader + EpicMorg, kasthack, stam Atlassian Downloader by EpicMorg https://github.com/EpicMorg/atlassian-downloader favicon.png @@ -23,6 +23,7 @@ EpicMorg 2021 Atlassian Downloader true + EpicMorg