From eb12c012a3a08ba25464802074a0e64511d4933f Mon Sep 17 00:00:00 2001 From: Wizzy69 Date: Mon, 25 Apr 2022 14:16:34 +0300 Subject: [PATCH] Improved download system --- DiscordBot/Program.cs | 41 ++-- PluginManager/Language System/Language.cs | 2 +- PluginManager/Loaders/PluginLoader.cs | 2 +- PluginManager/Online/Downloader.cs | 82 -------- .../Online/Helpers/OnlineFunctions.cs | 50 +++++ PluginManager/Online/LanguageManager.cs | 24 +-- PluginManager/Online/PluginsManager.cs | 23 +-- PluginManager/Online/ServerCom.cs | 42 +++- PluginManager/Others/Console Utilities.cs | 180 ++++++++++++++++++ PluginManager/Others/Functions.cs | 178 ++++------------- 10 files changed, 354 insertions(+), 270 deletions(-) delete mode 100644 PluginManager/Online/Downloader.cs create mode 100644 PluginManager/Online/Helpers/OnlineFunctions.cs create mode 100644 PluginManager/Others/Console Utilities.cs diff --git a/DiscordBot/Program.cs b/DiscordBot/Program.cs index f275e73..7962b1e 100644 --- a/DiscordBot/Program.cs +++ b/DiscordBot/Program.cs @@ -86,7 +86,7 @@ namespace DiscordBot while (true) { Console.ForegroundColor = ConsoleColor.White; - Functions.WriteColorText("&mConsole > &c", false); + Console_Utilities.WriteColorText("&mConsole > &c", false); string[] data = Console.ReadLine().Split(' '); if (data[0].Length < 2) continue; @@ -123,15 +123,19 @@ namespace DiscordBot { if (name == "") { - Functions.WriteColorText($"Name is invalid"); + Console_Utilities.WriteColorText($"Name is invalid"); break; } - Functions.WriteColorText($"Failed to find plugin &b{name} &c! Use &glistplugs &ccommand to display all available plugins !"); + Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c! Use &glistplugs &ccommand to display all available plugins !"); break; } - Downloader dw = new Downloader(name + ".dll", info[1]); - await dw.DownloadFileAsync("./Data/Plugins/", info[0]); + string path = "./Data/Plugins/" + info[0] + "s/" + name + ".dll"; + IProgress progress = new Progress(percent => + { + Console.Title = $"Downloading {info[0]}: {name} ({MathF.Round(percent, 2)}%)"; + }); + await ServerCom.DownloadFileAsync(info[1], path, progress); // check requirements if any @@ -146,7 +150,7 @@ namespace DiscordBot string[] split = line.Split(','); Console.WriteLine($"Downloading item: {split[1]}"); await ServerCom.DownloadFileAsync(split[0], "./" + split[1], i, lines.Count); - Functions.WriteColorText($"Downloaded item {split[1]}"); + Console_Utilities.WriteColorText($"Downloaded item {split[1]}"); i++; } Console.WriteLine(); @@ -175,28 +179,33 @@ namespace DiscordBot { if (Lname == "") { - Functions.WriteColorText($"Name is invalid"); + Console_Utilities.WriteColorText($"Name is invalid"); break; } - Functions.WriteColorText("Failed to find language &b" + Lname + " &c! Use &glistlang &ccommand to display all available languages !"); + Console_Utilities.WriteColorText("Failed to find language &b" + Lname + " &c! Use &glistlang &ccommand to display all available languages !"); break; } if (link[1].Contains("CrossPlatform") || link[1].Contains("cp")) { - Downloader dwn = new Downloader(Lname + ".lng", link[0]); - await dwn.DownloadFileAsync(Functions.langFolder); + + string path2 = Functions.langFolder + Lname + ".lng"; + IProgress progress1 = new Progress(percent => + { + Console.Title = $"Downloading Language: {Lname} ({MathF.Round(percent, 2)}%)"; + }); + await ServerCom.DownloadFileAsync(link[0], path2, progress1); } - else Functions.WriteColorText("The language you are trying to download (&b" + Lname + "&c) is not compatible with the version of this bot. User &glistlang &ccommand in order to see all available languages for your current version !\n" + link[1]); + else Console_Utilities.WriteColorText("The language you are trying to download (&b" + Lname + "&c) is not compatible with the version of this bot. User &glistlang &ccommand in order to see all available languages for your current version !\n" + link[1]); break; } catch { if (Lname == "") { - Functions.WriteColorText($"Name is invalid"); + Console_Utilities.WriteColorText($"Name is invalid"); break; } - Functions.WriteColorText("Failed to find language &b" + Lname + " &c! Use &glistlang &ccommand to display all available languages !"); + Console_Utilities.WriteColorText("Failed to find language &b" + Lname + " &c! Use &glistlang &ccommand to display all available languages !"); break; } @@ -301,7 +310,7 @@ namespace DiscordBot if (Language.ActiveLanguage == null) { File.WriteAllText(langSettings, "Language=English"); - Functions.WriteColorText($"Failed to find language &r{langname} &c! Check available languages using command: &glistlang"); + Console_Utilities.WriteColorText($"Failed to find language &r{langname} &c! Check available languages using command: &glistlang"); return false; } @@ -319,13 +328,13 @@ namespace DiscordBot bool success = LoadLanguage(); if (success) { - Functions.WriteColorText($"Language has been setted to: &g{LanguageName}"); + Console_Utilities.WriteColorText($"Language has been setted to: &g{LanguageName}"); return; } } catch (Exception ex) { - Functions.WriteColorText($"Could not find language &r{LanguageName}."); + Console_Utilities.WriteColorText($"Could not find language &r{LanguageName}."); Functions.WriteErrFile(ex.ToString()); File.WriteAllText(langSettings, "Language=English"); LoadLanguage(); diff --git a/PluginManager/Language System/Language.cs b/PluginManager/Language System/Language.cs index 97a68a6..d9fe518 100644 --- a/PluginManager/Language System/Language.cs +++ b/PluginManager/Language System/Language.cs @@ -29,7 +29,7 @@ namespace PluginManager.LanguageSystem { if (!LanguageFileLocation.EndsWith(LanguageFileExtension)) { - Console.WriteLine("Failed to load Language from file: " + LanguageFileLocation + + Console.WriteLine("Failed to load language from file: " + LanguageFileLocation + "\nFile extension is not .lng"); return null; } diff --git a/PluginManager/Loaders/PluginLoader.cs b/PluginManager/Loaders/PluginLoader.cs index d223d58..ccff7aa 100644 --- a/PluginManager/Loaders/PluginLoader.cs +++ b/PluginManager/Loaders/PluginLoader.cs @@ -40,7 +40,7 @@ namespace PluginManager.Loaders Functions.WriteLogFile("Starting plugin loader..."); if (LanguageSystem.Language.ActiveLanguage != null) - Functions.WriteColorText(LanguageSystem.Language.ActiveLanguage.FormatText(LanguageSystem.Language.ActiveLanguage.LanguageWords["PLUGIN_LOADING_START"])); + Console_Utilities.WriteColorText(LanguageSystem.Language.ActiveLanguage.FormatText(LanguageSystem.Language.ActiveLanguage.LanguageWords["PLUGIN_LOADING_START"])); //Load commands CommandsLoader CMDLoader = new CommandsLoader(pluginCMDFolder, pluginCMDExtension); diff --git a/PluginManager/Online/Downloader.cs b/PluginManager/Online/Downloader.cs deleted file mode 100644 index ff8190c..0000000 --- a/PluginManager/Online/Downloader.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.IO; -using System.Net; -using System.Threading.Tasks; - -using PluginManager.Items; - -namespace PluginManager.Online -{ - public class Downloader - { - public bool isWorking { get; private set; } - - public int percent { get; private set; } - private string fileName; - private string downloadLink; - - public Downloader(string fileName, string fileLink) - { - this.downloadLink = fileLink; - this.fileName = fileName; - } - - - public async Task DownloadFileAsync(string location = @"./Downloads/", string? pluginType = null, string? customMessage = null) - { - if (customMessage != null) - Console.WriteLine(customMessage); - - Directory.CreateDirectory(location); - if (isWorking) return; - isWorking = true; - percent = 0; - - Spinner s = new Spinner(); - Console.Write("Downloading:\t\t"); - s.Start(); - -#pragma warning disable SYSLIB0014 - WebClient client = new WebClient(); -#pragma warning restore SYSLIB0014 - - client.DownloadFileCompleted += (sender, args) => - { - isWorking = false; - s.Stop(); - var c = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.DarkGreen; - Console.Write("OK"); - Console.ForegroundColor = c; - Console.Write(" !\n"); - //Console.WriteLine("Your plugin has been successfully downloaded !"); - if (pluginType == "Event/Command" || pluginType == "Command/Event") - { - File.Copy(location + fileName, location + "Commands/" + fileName, true); - File.Move(location + fileName, location + "Events/" + fileName, true); - } - - }; - - string l = ""; - if (pluginType == "Command") - l = location + "Commands/" + fileName; - else if (pluginType == "Event") - l = location + "Events/" + fileName; - else l = location + fileName; - try - { - await client.DownloadFileTaskAsync(new Uri(this.downloadLink), l); - } - catch - { - var c = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Console.Write("FAIL"); - Console.ForegroundColor = c; - Console.Write(" !\n"); - } - } - - } -} diff --git a/PluginManager/Online/Helpers/OnlineFunctions.cs b/PluginManager/Online/Helpers/OnlineFunctions.cs new file mode 100644 index 0000000..ba2bcbf --- /dev/null +++ b/PluginManager/Online/Helpers/OnlineFunctions.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Net.Http; +using System.Threading.Tasks; +using System.IO; +using System.Threading; +using PluginManager.Others; + +namespace PluginManager.Online.Helpers +{ + internal static class OnlineFunctions + { + internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination, IProgress progress = null, CancellationToken cancellation = default) + { + using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead)) + { + var contentLength = response.Content.Headers.ContentLength; + + using (var download = await response.Content.ReadAsStreamAsync()) + { + + // Ignore progress reporting when no progress reporter was + // passed or when the content length is unknown + if (progress == null || !contentLength.HasValue) + { + await download.CopyToAsync(destination); + return; + } + + // Convert absolute progress (bytes downloaded) into relative progress (0% - 100%) + var relativeProgress = new Progress(totalBytes => progress.Report((float)totalBytes / contentLength.Value * 100)); + // Use extension method to report progress while downloading + await download.CopyToOtherStreamAsync(destination, 81920, relativeProgress, cancellation); + progress.Report(1); + } + } + } + + internal static async Task DownloadStringAsync(string url, CancellationToken cancellation = default) + { + using (var client = new HttpClient()) + { + return await client.GetStringAsync(url); + } + } + } +} diff --git a/PluginManager/Online/LanguageManager.cs b/PluginManager/Online/LanguageManager.cs index 5c97711..0389922 100644 --- a/PluginManager/Online/LanguageManager.cs +++ b/PluginManager/Online/LanguageManager.cs @@ -15,13 +15,17 @@ namespace PluginManager.Online public async Task ListAllLanguages() { + try { -#pragma warning disable SYSLIB0014 - WebClient client = new WebClient(); -#pragma warning restore SYSLIB0014 - Stream data = await client.OpenReadTaskAsync(link); - string[] lines = (await new StreamReader(data).ReadToEndAsync()).Split('\n'); + /*#pragma warning disable SYSLIB0014 + WebClient client = new WebClient(); + #pragma warning restore SYSLIB0014 + Stream data = await client.OpenReadTaskAsync(link); + string[] lines = (await new StreamReader(data).ReadToEndAsync()).Split('\n');*/ + List list = await ServerCom.ReadTextFromFile(link); + string[] lines = list.ToArray(); + List info = new List(); info.Add(new string[] { "-", "-" }); info.Add(new string[] { "Language Name", "File Size" }); @@ -34,7 +38,7 @@ namespace PluginManager.Online info.Add(new string[] { d[0], d[1] }); } info.Add(new string[] { "-", "-" }); - Functions.FormatAndAlignTable(info); + Console_Utilities.FormatAndAlignTable(info); } catch (Exception exception) @@ -49,11 +53,9 @@ namespace PluginManager.Online { try { -#pragma warning disable SYSLIB0014 - WebClient client = new WebClient(); -#pragma warning restore SYSLIB0014 - Stream data = await client.OpenReadTaskAsync(link); - string[] lines = (await new StreamReader(data).ReadToEndAsync()).Split('\n'); + List list = await ServerCom.ReadTextFromFile(link); + string[] lines = list.ToArray(); + foreach (var line in lines) { if (line.Length <= 2) continue; diff --git a/PluginManager/Online/PluginsManager.cs b/PluginManager/Online/PluginsManager.cs index dc47cf6..581f6ca 100644 --- a/PluginManager/Online/PluginsManager.cs +++ b/PluginManager/Online/PluginsManager.cs @@ -21,16 +21,12 @@ namespace PluginManager.Online { try { -#pragma warning disable SYSLIB0014 - WebClient client = new WebClient(); -#pragma warning restore SYSLIB0014 - Stream s = await client.OpenReadTaskAsync(PluginsLink); - string text = await new StreamReader(s).ReadToEndAsync(); - + List list = await ServerCom.ReadTextFromFile(PluginsLink); + string[] lines = list.ToArray(); List data = new List(); var op = Functions.GetOperatinSystem(); - string[] lines = text.Split('\n'); + int len = lines.Length; string[] titles = { "Name", "Description", "Plugin Type", "Libraries" }; data.Add(new string[] { "-", "-", "-", "-" }); @@ -41,7 +37,7 @@ namespace PluginManager.Online if (lines[i].Length <= 2) continue; string[] content = lines[i].Split(','); string[] display = new string[4]; - if (op == PluginManager.Others.OperatingSystem.WINDOWS) + if (op == Others.OperatingSystem.WINDOWS) { if (content[4].Contains("Windows")) { @@ -71,7 +67,7 @@ namespace PluginManager.Online data.Add(new string[] { "-", "-", "-", "-" }); - Functions.FormatAndAlignTable(data); + Console_Utilities.FormatAndAlignTable(data); } catch (Exception exception) { @@ -85,13 +81,8 @@ namespace PluginManager.Online { try { -#pragma warning disable SYSLIB0014 - WebClient client = new WebClient(); -#pragma warning restore SYSLIB0014 - Stream s = await client.OpenReadTaskAsync(PluginsLink); - string text = await new StreamReader(s).ReadToEndAsync(); - - string[] lines = text.Split('\n'); + List list = await ServerCom.ReadTextFromFile(PluginsLink); + string[] lines = list.ToArray(); int len = lines.Length; for (int i = 0; i < len; i++) { diff --git a/PluginManager/Online/ServerCom.cs b/PluginManager/Online/ServerCom.cs index 7ec9209..264ee45 100644 --- a/PluginManager/Online/ServerCom.cs +++ b/PluginManager/Online/ServerCom.cs @@ -1,4 +1,5 @@ using PluginManager.Items; +using PluginManager.Online.Helpers; using System; using System.Collections.Generic; @@ -14,6 +15,14 @@ namespace PluginManager.Online { public static async Task> ReadTextFromFile(string link) { + string response = await OnlineFunctions.DownloadStringAsync(link); + string[] lines = response.Split('\n'); + return lines.ToList(); + + + //[Obsolete] + #region old code for reading text from link + /* List s = new List(); WebClient webClient = new WebClient(); var data = await webClient.OpenReadTaskAsync(link); @@ -21,12 +30,38 @@ namespace PluginManager.Online s.AddRange(from a in response.Split('\n') where !a.StartsWith("$") select a); - return s; + return s;*/ + #endregion + } + + public static async Task DownloadFileAsync(string URL, string location, IProgress progress) + { + using (var client = new System.Net.Http.HttpClient()) + { + client.Timeout = TimeSpan.FromMinutes(5); + + using (var file = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.None)) + { + await client.DownloadFileAsync(URL, file, progress); + } + } } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] public static async Task DownloadFileAsync(string url, string location, int downloadNumber, int totalToDownload) { + + IProgress progress = new Progress(bytes => + { + Console.Title = $"Downloading {MathF.Round(bytes, 2)}% ({downloadNumber}/{totalToDownload})"; + }); + + await DownloadFileAsync(url, location, progress); + Console.Title = "ONLINE"; + return; + + //[Obsolete] + #region old download code + /* WebClient client = new WebClient(); Spinner spinner = new Spinner(); Console.Write("Downloading "); @@ -52,8 +87,9 @@ namespace PluginManager.Online finally { Console.Title = oldTitle; - } + }*/ + #endregion } } } diff --git a/PluginManager/Others/Console Utilities.cs b/PluginManager/Others/Console Utilities.cs new file mode 100644 index 0000000..a21d6b7 --- /dev/null +++ b/PluginManager/Others/Console Utilities.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PluginManager.Others +{ + public class Console_Utilities + { + const char _block = '■'; + const string _back = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; + const string _twirl = "-\\|/"; + public static void WriteProgressBar(int percent, bool update = false) + { + if (update) + Console.Write(_back); + Console.Write("["); + var p = (int)((percent / 10f) + .5f); + for (var i = 0; i < 10; ++i) + { + if (i >= p) + Console.Write(' '); + else + Console.Write(_block); + } + Console.Write("] {0,3:##0}%", percent); + + if (percent == 100) + Console.WriteLine(); + } + public static void WriteProgress(int progress, bool update = false) + { + if (update) + Console.Write("\b"); + Console.Write(_twirl[progress % _twirl.Length]); + } + + /// + /// A way to create a table based on input data + /// + /// The List of arrays of strings that represent the rows. + public static void FormatAndAlignTable(List data) + { + char tableLine = '-'; + char tableCross = '+'; + char tableWall = '|'; + + int[] len = new int[data[0].Length]; + foreach (var line in data) + { + for (int i = 0; i < line.Length; i++) + if (line[i].Length > len[i]) + len[i] = line[i].Length; + } + + + foreach (string[] row in data) + { + //Console.Write("\t"); + if (row[0][0] == tableLine) Console.Write(tableCross); + else Console.Write(tableWall); + for (int l = 0; l < row.Length; l++) + { + if (row[l][0] == tableLine) + { + for (int i = 0; i < len[l] + 4; ++i) + Console.Write(tableLine); + } + else if (row[l].Length == len[l]) + { + Console.Write(" "); + Console.Write(row[l]); + Console.Write(" "); + } + else + { + + int lenHalf = row[l].Length / 2; + for (int i = 0; i < ((len[l] + 4) / 2 - lenHalf); ++i) + Console.Write(" "); + Console.Write(row[l]); + for (int i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i) + Console.Write(" "); + if (row[l].Length % 2 == 0) + Console.Write(" "); + } + + if (row[l][0] == tableLine) Console.Write(tableCross); + else Console.Write(tableWall); + } + Console.WriteLine(); //end line + + } + + + //Obsolite + #region Old Code -> Spacing by the lomgest item in any cell + /* + int maxLen = 0; + foreach (string[] row in data) + foreach (string s in row) + if (s.Length > maxLen) + maxLen = s.Length; + + int div = (maxLen + 4) / 2; + + foreach (string[] row in data) + { + //Console.Write("\t"); + if (row[0] == "-") Console.Write("+"); + else Console.Write("|"); + + foreach (string s in row) + { + if (s == "-") + { + for (int i = 0; i < maxLen + 4; ++i) + Console.Write("-"); + } + else if (s.Length == maxLen) + { + Console.Write(" "); + Console.Write(s); + Console.Write(" "); + } + else + { + int lenHalf = s.Length / 2; + for (int i = 0; i < div - lenHalf; ++i) + Console.Write(" "); + Console.Write(s); + for (int i = div + lenHalf + 1; i < maxLen + 4; ++i) + Console.Write(" "); + if (s.Length % 2 == 0) + Console.Write(" "); + } + + if (s == "-") Console.Write("+"); + else Console.Write("|"); + } + Console.WriteLine(); //end line + }*/ + #endregion + } + + /// + /// Write the text using color options( &g-green; &b-blue; &r-red; &c-clear; ) + /// + /// + /// The text + public static void WriteColorText(string text, bool appendNewLine = true) + { + string[] words = text.Split(' '); + Dictionary colors = new Dictionary() + { + {"&g", ConsoleColor.Green }, + {"&b", ConsoleColor.Blue }, + {"&r", ConsoleColor.Red }, + {"&m", ConsoleColor.Magenta }, + {"&c", Console.ForegroundColor } + }; + foreach (string word in words) + { + if (word.Length >= 2) + { + string prefix = word.Substring(0, 2); + if (colors.ContainsKey(prefix)) + Console.ForegroundColor = colors[prefix]; + } + + string m = word.Replace("&g", "").Replace("&b", "").Replace("&r", "").Replace("&c", "").Replace("&m", ""); + Console.Write(m + " "); + } + if (appendNewLine) + Console.Write('\n'); + } + + } +} diff --git a/PluginManager/Others/Functions.cs b/PluginManager/Others/Functions.cs index f8cece8..fb23cd5 100644 --- a/PluginManager/Others/Functions.cs +++ b/PluginManager/Others/Functions.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Collections.Generic; using Discord.WebSocket; using PluginManager.Items; +using System.Threading; namespace PluginManager.Others { @@ -175,146 +176,6 @@ namespace PluginManager.Others } - /// - /// A way to create a table based on input data - /// - /// The List of arrays of strings that represent the rows. - public static void FormatAndAlignTable(List data) - { - char tableLine = '-'; - char tableCross = '+'; - char tableWall = '|'; - - int[] len = new int[data[0].Length]; - foreach (var line in data) - { - for (int i = 0; i < line.Length; i++) - if (line[i].Length > len[i]) - len[i] = line[i].Length; - } - - - foreach (string[] row in data) - { - //Console.Write("\t"); - if (row[0][0] == tableLine) Console.Write(tableCross); - else Console.Write(tableWall); - for (int l = 0; l < row.Length; l++) - { - if (row[l][0] == tableLine) - { - for (int i = 0; i < len[l] + 4; ++i) - Console.Write(tableLine); - } - else if (row[l].Length == len[l]) - { - Console.Write(" "); - Console.Write(row[l]); - Console.Write(" "); - } - else - { - - int lenHalf = row[l].Length / 2; - for (int i = 0; i < ((len[l] + 4) / 2 - lenHalf); ++i) - Console.Write(" "); - Console.Write(row[l]); - for (int i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i) - Console.Write(" "); - if (row[l].Length % 2 == 0) - Console.Write(" "); - } - - if (row[l][0] == tableLine) Console.Write(tableCross); - else Console.Write(tableWall); - } - Console.WriteLine(); //end line - - } - - - //Obsolite - #region Old Code -> Spacing by the lomgest item in any cell - /* - int maxLen = 0; - foreach (string[] row in data) - foreach (string s in row) - if (s.Length > maxLen) - maxLen = s.Length; - - int div = (maxLen + 4) / 2; - - foreach (string[] row in data) - { - //Console.Write("\t"); - if (row[0] == "-") Console.Write("+"); - else Console.Write("|"); - - foreach (string s in row) - { - if (s == "-") - { - for (int i = 0; i < maxLen + 4; ++i) - Console.Write("-"); - } - else if (s.Length == maxLen) - { - Console.Write(" "); - Console.Write(s); - Console.Write(" "); - } - else - { - int lenHalf = s.Length / 2; - for (int i = 0; i < div - lenHalf; ++i) - Console.Write(" "); - Console.Write(s); - for (int i = div + lenHalf + 1; i < maxLen + 4; ++i) - Console.Write(" "); - if (s.Length % 2 == 0) - Console.Write(" "); - } - - if (s == "-") Console.Write("+"); - else Console.Write("|"); - } - Console.WriteLine(); //end line - }*/ - #endregion - } - - /// - /// Write the text using color options( &g-green; &b-blue; &r-red; &c-clear; ) - /// - /// - /// The text - public static void WriteColorText(string text, bool appendNewLine = true) - { - string[] words = text.Split(' '); - Dictionary colors = new Dictionary() - { - {"&g", ConsoleColor.Green }, - {"&b", ConsoleColor.Blue }, - {"&r", ConsoleColor.Red }, - {"&m", ConsoleColor.Magenta }, - {"&c", Console.ForegroundColor } - }; - foreach (string word in words) - { - if (word.Length >= 2) - { - string prefix = word.Substring(0, 2); - if (colors.ContainsKey(prefix)) - Console.ForegroundColor = colors[prefix]; - } - - string m = word.Replace("&g", "").Replace("&b", "").Replace("&r", "").Replace("&c", "").Replace("&m", ""); - Console.Write(m + " "); - } - if (appendNewLine) - Console.Write('\n'); - } - /// /// Write setting /// @@ -361,5 +222,42 @@ namespace PluginManager.Others return sb.ToString(); } + + /// + /// Copy one Stream to another + /// + /// The base stream + /// The destination stream + /// The buffer to read + /// The progress + /// The cancellation token + /// Triggered if any is empty + /// Triggered if is less then or equal to 0 + /// Triggered if is not readable + /// Triggered in is not writable + public static async Task CopyToOtherStreamAsync(this Stream stream, Stream destination, int bufferSize, IProgress progress = null, CancellationToken cancellationToken = default) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + if (destination == null) + throw new ArgumentNullException(nameof(destination)); + if (bufferSize <= 0) + throw new ArgumentOutOfRangeException(nameof(bufferSize)); + if (!stream.CanRead) + throw new InvalidOperationException("The stream is not readable."); + if (!destination.CanWrite) + throw new ArgumentException("Destination stream is not writable", nameof(destination)); + + byte[] buffer = new byte[bufferSize]; + long totalBytesRead = 0; + int bytesRead; + while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + { + await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); + totalBytesRead += bytesRead; + progress?.Report(totalBytesRead); + } + + } } }