2022-06-03 03:43:34 +00:00
|
|
|
|
using Discord;
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2022-08-24 03:39:44 +00:00
|
|
|
|
using System.Text;
|
2022-07-13 06:45:18 +00:00
|
|
|
|
using System.Text.RegularExpressions;
|
2022-06-03 03:43:34 +00:00
|
|
|
|
|
|
|
|
|
namespace RegexBot.Common;
|
|
|
|
|
/// <summary>
|
2022-07-09 20:22:39 +00:00
|
|
|
|
/// Miscellaneous utility methods useful for the bot and modules.
|
2022-06-03 03:43:34 +00:00
|
|
|
|
/// </summary>
|
2022-07-09 20:22:39 +00:00
|
|
|
|
public static class Utilities {
|
2022-07-21 01:55:08 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a compiled regex that matches a channel tag and pulls its snowflake value.
|
|
|
|
|
/// </summary>
|
2022-07-13 06:45:18 +00:00
|
|
|
|
public static Regex ChannelMention { get; } = new(@"<#(?<snowflake>\d+)>", RegexOptions.Compiled);
|
2022-07-21 01:55:08 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a compiled regex that matches a custom emoji and pulls its name and ID.
|
|
|
|
|
/// </summary>
|
2022-07-13 06:45:18 +00:00
|
|
|
|
public static Regex CustomEmoji { get; } = new(@"<:(?<name>[A-Za-z0-9_]{2,}):(?<ID>\d+)>", RegexOptions.Compiled);
|
2022-07-21 01:55:08 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a compiled regex that matches a fully formed Discord handle, extracting the name and discriminator.
|
|
|
|
|
/// </summary>
|
2022-07-13 06:45:18 +00:00
|
|
|
|
public static Regex DiscriminatorSearch { get; } = new(@"(.+)#(\d{4}(?!\d))", RegexOptions.Compiled);
|
2022-07-21 01:55:08 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a compiled regex that matches a user tag and pulls its snowflake value.
|
|
|
|
|
/// </summary>
|
2022-07-13 06:45:18 +00:00
|
|
|
|
public static Regex UserMention { get; } = new(@"<@!?(?<snowflake>\d+)>", RegexOptions.Compiled);
|
|
|
|
|
|
2022-06-03 03:43:34 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Performs common checks on the specified message to see if it fits all the criteria of a
|
|
|
|
|
/// typical, ordinary message sent by an ordinary guild user.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool IsValidUserMessage(SocketMessage msg, [NotNullWhen(true)] out SocketTextChannel? channel) {
|
|
|
|
|
channel = default;
|
|
|
|
|
if (msg.Channel is not SocketTextChannel ch) return false;
|
|
|
|
|
if (msg.Author.IsBot || msg.Author.IsWebhook) return false;
|
|
|
|
|
if (((IMessage)msg).Type != MessageType.Default) return false;
|
|
|
|
|
if (msg is SocketSystemMessage) return false;
|
|
|
|
|
channel = ch;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2022-07-06 03:59:19 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Given a JToken, gets all string-based values out of it if the token may be a string
|
|
|
|
|
/// or an array of strings.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token">The JSON token to analyze and retrieve strings from.</param>
|
|
|
|
|
/// <exception cref="ArgumentException">Thrown if the given token is not a string or array containing all strings.</exception>
|
|
|
|
|
/// <exception cref="ArgumentNullException">Thrown if the given token is null.</exception>
|
|
|
|
|
public static List<string> LoadStringOrStringArray(JToken? token) {
|
|
|
|
|
const string ExNotString = "This token contains a non-string element.";
|
|
|
|
|
if (token == null) throw new ArgumentNullException(nameof(token), "The provided token is null.");
|
|
|
|
|
var results = new List<string>();
|
|
|
|
|
if (token.Type == JTokenType.String) {
|
|
|
|
|
results.Add(token.Value<string>()!);
|
|
|
|
|
} else if (token.Type == JTokenType.Array) {
|
|
|
|
|
foreach (var entry in token.Values()) {
|
|
|
|
|
if (entry.Type != JTokenType.String) throw new ArgumentException(ExNotString, nameof(token));
|
|
|
|
|
results.Add(entry.Value<string>()!);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
throw new ArgumentException(ExNotString, nameof(token));
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
}
|
2022-08-24 03:39:44 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Builds and returns an embed which displays this log entry.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static Embed BuildEmbed(this Data.ModLogEntry entry, RegexbotClient bot) {
|
2022-10-05 19:40:53 +00:00
|
|
|
|
var issuedDisplay = TryFromEntityNameString(entry.IssuedBy, bot);
|
2022-08-24 03:39:44 +00:00
|
|
|
|
string targetDisplay;
|
|
|
|
|
var targetq = bot.EcQueryUser(entry.UserId.ToString());
|
|
|
|
|
if (targetq != null) targetDisplay = $"<@{targetq.UserId}> - {targetq.Username}#{targetq.Discriminator} `{targetq.UserId}`";
|
2022-09-21 04:50:33 +00:00
|
|
|
|
else targetDisplay = $"User with ID `{entry.UserId}`";
|
|
|
|
|
|
|
|
|
|
var logEmbed = new EmbedBuilder()
|
|
|
|
|
.WithTitle(Enum.GetName(typeof(ModLogType), entry.LogType) + " logged:")
|
|
|
|
|
.WithTimestamp(entry.Timestamp)
|
|
|
|
|
.WithFooter($"Log #{entry.LogId}", bot.DiscordClient.CurrentUser.GetAvatarUrl()); // Escaping '#' not necessary here
|
|
|
|
|
if (entry.Message != null) {
|
|
|
|
|
logEmbed.Description = entry.Message;
|
|
|
|
|
}
|
2022-08-24 03:39:44 +00:00
|
|
|
|
|
|
|
|
|
var contextStr = new StringBuilder();
|
2022-09-21 04:50:33 +00:00
|
|
|
|
contextStr.AppendLine($"User: {targetDisplay}");
|
2022-08-24 03:39:44 +00:00
|
|
|
|
contextStr.AppendLine($"Logged by: {issuedDisplay}");
|
|
|
|
|
|
|
|
|
|
logEmbed.AddField(new EmbedFieldBuilder() {
|
|
|
|
|
Name = "Context",
|
|
|
|
|
Value = contextStr.ToString()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return logEmbed.Build();
|
|
|
|
|
}
|
2022-09-21 04:50:33 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns a representation of this entity that can be parsed by the <seealso cref="EntityName"/> constructor.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static string AsEntityNameString(this IUser entity) => $"@{entity.Id}::{entity.Username}";
|
2022-10-05 19:40:53 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// If given string is in an EntityName format, returns a displayable representation of it based on
|
|
|
|
|
/// a cache query. Otherwise, returns the input string as-is.
|
|
|
|
|
/// </summary>
|
|
|
|
|
[return: NotNullIfNotNull("input")]
|
|
|
|
|
public static string? TryFromEntityNameString(string? input, RegexbotClient bot) {
|
|
|
|
|
string? result = null;
|
|
|
|
|
try {
|
|
|
|
|
var entityTry = new EntityName(input!, EntityType.User);
|
|
|
|
|
var issueq = bot.EcQueryUser(entityTry.Id!.Value.ToString());
|
|
|
|
|
if (issueq != null) result = $"<@{issueq.UserId}> - {issueq.Username}#{issueq.Discriminator} `{issueq.UserId}`";
|
|
|
|
|
else result = $"Unknown user with ID `{entityTry.Id!.Value}`";
|
|
|
|
|
} catch (Exception) { }
|
|
|
|
|
return result ?? input;
|
|
|
|
|
}
|
2022-06-03 03:43:34 +00:00
|
|
|
|
}
|