Files
nadekobot/src/NadekoBot/_Extensions/StringExtensions.cs
2021-12-20 03:54:30 +01:00

187 lines
5.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Newtonsoft.Json;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using NadekoBot.Common.Yml;
namespace NadekoBot.Extensions;
public static class StringExtensions
{
public static string PadBoth(this string str, int length)
{
var spaces = length - str.Length;
var padLeft = spaces / 2 + str.Length;
return str.PadLeft(padLeft).PadRight(length);
}
public static T MapJson<T>(this string str)
=> JsonConvert.DeserializeObject<T>(str);
private static readonly HashSet<char> lettersAndDigits = new HashSet<char>(Enumerable.Range(48, 10)
.Concat(Enumerable.Range(65, 26))
.Concat(Enumerable.Range(97, 26))
.Select(x => (char)x));
public static string StripHTML(this string input)
{
return Regex.Replace(input, "<.*?>", String.Empty);
}
// todo future maybe use humanizer lib for this kind of work
public static string TrimTo(this string str, int maxLength, bool hideDots = false)
{
if (maxLength < 0)
throw new ArgumentOutOfRangeException(nameof(maxLength), $"Argument {nameof(maxLength)} can't be negative.");
if (maxLength == 0)
return string.Empty;
if (maxLength <= 3)
return string.Concat(str.Select(c => '.'));
if (str.Length < maxLength)
return str;
if (hideDots)
{
return string.Concat(str.Take(maxLength));
}
else
{
return string.Concat(str.Take(maxLength - 1)) + "…";
}
}
public static string ToTitleCase(this string str)
{
var tokens = str.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < tokens.Length; i++)
{
var token = tokens[i];
tokens[i] = token.Substring(0, 1).ToUpperInvariant() + token.Substring(1);
}
return string.Join(" ", tokens)
.Replace(" Of ", " of ")
.Replace(" The ", " the ");
}
/// <summary>
/// Removes trailing S or ES (if specified) on the given string if the num is 1
/// </summary>
/// <param name="str"></param>
/// <param name="num"></param>
/// <param name="es"></param>
/// <returns>String with the correct singular/plural form</returns>
public static string SnPl(this string str, int? num, bool es = false)
{
if (str is null)
throw new ArgumentNullException(nameof(str));
if (num is null)
throw new ArgumentNullException(nameof(num));
return num == 1 ? str.Remove(str.Length - 1, es ? 2 : 1) : str;
}
//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 async Task<Stream> ToStream(this string str)
{
var ms = new MemoryStream();
var sw = new StreamWriter(ms);
await sw.WriteAsync(str).ConfigureAwait(false);
await sw.FlushAsync().ConfigureAwait(false);
ms.Position = 0;
return ms;
}
private static readonly Regex filterRegex = new Regex(@"discord(?:\.gg|\.io|\.me|\.li|(?:app)?\.com\/invite)\/(\w+)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static bool IsDiscordInvite(this string str)
=> filterRegex.IsMatch(str);
public static string Unmention(this string str) => str.Replace("@", "ම", StringComparison.InvariantCulture);
public static string SanitizeMentions(this string str, bool sanitizeRoleMentions = false)
{
str = str.Replace("@everyone", "@everyοne", StringComparison.InvariantCultureIgnoreCase)
.Replace("@here", "@һere", StringComparison.InvariantCultureIgnoreCase);
if (sanitizeRoleMentions)
str = str.SanitizeRoleMentions();
return str;
}
public static string SanitizeRoleMentions(this string str) =>
str.Replace("<@&", "<ම&", StringComparison.InvariantCultureIgnoreCase);
public static string SanitizeAllMentions(this string str) =>
str.SanitizeMentions().SanitizeRoleMentions();
public static string ToBase64(this string plainText)
{
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
public static string GetInitials(this string txt, string glue = "") =>
string.Join(glue, txt.Split(' ').Select(x => x.FirstOrDefault()));
public static bool IsAlphaNumeric(this string txt) =>
txt.All(c => lettersAndDigits.Contains(c));
private static readonly Regex CodePointRegex
= new Regex(@"(\\U(?<code>[a-zA-Z0-9]{8})|\\u(?<code>[a-zA-Z0-9]{4})|\\x(?<code>[a-zA-Z0-9]{2}))",
RegexOptions.Compiled);
public static string UnescapeUnicodeCodePoints(this string input)
{
return CodePointRegex.Replace(input, me =>
{
var str = me.Groups["code"].Value;
var newString = YamlHelper.UnescapeUnicodeCodePoint(str);
return newString;
});
}
}