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);
}
}