using Discord; using Discord.Commands; using NadekoBot.Classes; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Threading.Tasks; namespace NadekoBot.Extensions { public static class Extensions { private static Random rng = new Random(); public static string Scramble(this string word) { var letters = word.ToArray(); var count = 0; for (var i = 0; i < letters.Length; i++) { if (letters[i] == ' ') continue; count++; if (count <= letters.Length / 5) continue; if (count % 3 == 0) continue; if (letters[i] != ' ') letters[i] = '_'; } return "`" + string.Join(" ", letters) + "`"; } public static string TrimTo(this string str, int num, bool hideDots = false) { if (num < 0) throw new ArgumentOutOfRangeException(nameof(num), "TrimTo argument cannot be less than 0"); if (num == 0) return string.Empty; if (num <= 3) return string.Join("", str.Select(c => '.')); if (str.Length < num) return str; return string.Join("", str.Take(num - 3)) + (hideDots ? "" : "..."); } /// /// Removes trailing S or ES (if specified) on the given string if the num is 1 /// /// /// /// /// String with the correct singular/plural form public static string SnPl(this string str, int? num, bool es = false) { if (str == null) throw new ArgumentNullException(nameof(str)); if (num == null) throw new ArgumentNullException(nameof(num)); return num == 1 ? str.Remove(str.Length - 1, es ? 2 : 1) : str; } /// /// Sends a message to the channel from which this command is called. /// /// EventArg /// Message to be sent /// public static async Task Send(this CommandEventArgs e, string message) => await e.Channel.SendMessage(message).ConfigureAwait(false); /// /// Sends a message to the channel from which MessageEventArg came. /// /// EventArg /// Message to be sent /// public static async Task Send(this MessageEventArgs e, string message) { if (string.IsNullOrWhiteSpace(message)) return; await e.Channel.SendMessage(message).ConfigureAwait(false); } /// /// Sends a message to this channel. /// /// /// /// public static async Task Send(this Channel c, string message) { await c.SendMessage(message).ConfigureAwait(false); } /// /// Sends a private message to this user. /// /// /// /// public static async Task Send(this User u, string message) { await u.SendMessage(message).ConfigureAwait(false); } /// /// Replies to a user who invoked this command, message start with that user's mention. /// /// /// /// public static async Task Reply(this CommandEventArgs e, string message) { await e.Channel.SendMessage(e.User.Mention + " " + message).ConfigureAwait(false); } /// /// Replies to a user who invoked this command, message start with that user's mention. /// /// /// /// public static async Task Reply(this MessageEventArgs e, string message) { await e.Channel.SendMessage(e.User.Mention + " " + message).ConfigureAwait(false); } /// /// Randomizes element order in a list /// /// /// public static void Shuffle(this IList list) { // Thanks to @Joe4Evr for finding a bug in the old version of the shuffle var provider = new RNGCryptoServiceProvider(); var n = list.Count; while (n > 1) { var box = new byte[(n / Byte.MaxValue) + 1]; int boxSum; do { provider.GetBytes(box); boxSum = box.Sum(b => b); } while (!(boxSum < n * ((Byte.MaxValue * box.Length) / n))); var k = (boxSum % n); n--; var value = list[k]; list[k] = list[n]; list[n] = value; } } /// /// Shortens a string URL /// /// /// /// public static async Task ShortenUrl(this string str) => await SearchHelper.ShortenUrl(str).ConfigureAwait(false); /// /// Gets the program runtime /// /// /// /// public static string GetRuntime(this DiscordClient c) => ".Net Framework 4.5.2"; public static string Matrix(this string s) => string.Join("", s.Select(c => c.ToString() + " ̵̢̬̜͉̞̭̖̰͋̉̎ͬ̔̇̌̀".TrimTo(rng.Next(0, 12), true))); //.Replace("`", ""); public static void ForEach(this IEnumerable source, Action action) { foreach (var element in source) { action(element); } } //http://www.dotnetperls.com/levenshtein public static int LevenshteinDistance(this string s, string t) { var n = s.Length; var m = t.Length; var d = new int[n + 1, m + 1]; // Step 1 if (n == 0) { return m; } if (m == 0) { return n; } // Step 2 for (var i = 0; i <= n; d[i, 0] = i++) { } for (var j = 0; j <= m; d[0, j] = j++) { } // Step 3 for (var i = 1; i <= n; i++) { //Step 4 for (var j = 1; j <= m; j++) { // Step 5 var cost = (t[j - 1] == s[i - 1]) ? 0 : 1; // Step 6 d[i, j] = Math.Min( Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), d[i - 1, j - 1] + cost); } } // Step 7 return d[n, m]; } public static int KiB(this int value) => value * 1024; public static int KB(this int value) => value * 1000; public static int MiB(this int value) => value.KiB() * 1024; public static int MB(this int value) => value.KB() * 1000; public static int GiB(this int value) => value.MiB() * 1024; public static int GB(this int value) => value.MB() * 1000; public static Stream ToStream(this Image img, System.Drawing.Imaging.ImageFormat format = null) { if (format == null) format = System.Drawing.Imaging.ImageFormat.Jpeg; var stream = new MemoryStream(); img.Save(stream, format); stream.Position = 0; return stream; } /// /// Merges Images into 1 Image and returns a bitmap. /// /// The Images you want to merge. /// Merged bitmap public static Bitmap Merge(this IEnumerable images, int reverseScaleFactor = 1) { var imageArray = images as Image[] ?? images.ToArray(); if (!imageArray.Any()) return null; var width = imageArray.Sum(i => i.Width); var height = imageArray.First().Height; var bitmap = new Bitmap(width / reverseScaleFactor, height / reverseScaleFactor); var r = new Random(); var offsetx = 0; foreach (var img in imageArray) { var bm = new Bitmap(img); for (var w = 0; w < img.Width; w++) { for (var h = 0; h < bitmap.Height; h++) { bitmap.SetPixel(w / reverseScaleFactor + offsetx, h, bm.GetPixel(w, h * reverseScaleFactor)); } } offsetx += img.Width / reverseScaleFactor; } return bitmap; } /// /// Merges Images into 1 Image and returns a bitmap asynchronously. /// /// The Images you want to merge. /// /// Merged bitmap public static async Task MergeAsync(this IEnumerable images, int reverseScaleFactor = 1) => await Task.Run(() => images.Merge(reverseScaleFactor)).ConfigureAwait(false); } }