mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
- Removed some duplicated code from custom reactions
- CREmbed completely removed and replaced by SmartText
This commit is contained in:
@@ -1,125 +0,0 @@
|
|||||||
using Discord;
|
|
||||||
using NadekoBot.Extensions;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using NadekoBot.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common
|
|
||||||
{
|
|
||||||
public class CREmbed
|
|
||||||
{
|
|
||||||
public CREmbedAuthor Author { get; set; }
|
|
||||||
public string PlainText { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string Url { get; set; }
|
|
||||||
public CREmbedFooter Footer { get; set; }
|
|
||||||
public string Thumbnail { get; set; }
|
|
||||||
public string Image { get; set; }
|
|
||||||
public CREmbedField[] Fields { get; set; }
|
|
||||||
public uint Color { get; set; } = 7458112;
|
|
||||||
|
|
||||||
public bool IsValid =>
|
|
||||||
IsEmbedValid || !string.IsNullOrWhiteSpace(PlainText);
|
|
||||||
public bool IsEmbedValid =>
|
|
||||||
!string.IsNullOrWhiteSpace(Title) ||
|
|
||||||
!string.IsNullOrWhiteSpace(Description) ||
|
|
||||||
!string.IsNullOrWhiteSpace(Url) ||
|
|
||||||
!string.IsNullOrWhiteSpace(Thumbnail) ||
|
|
||||||
!string.IsNullOrWhiteSpace(Image) ||
|
|
||||||
(Footer != null && (!string.IsNullOrWhiteSpace(Footer.Text) || !string.IsNullOrWhiteSpace(Footer.IconUrl))) ||
|
|
||||||
(Fields != null && Fields.Length > 0);
|
|
||||||
|
|
||||||
public IEmbedBuilder ToEmbed(IEmbedBuilderService eb)
|
|
||||||
{
|
|
||||||
var embed = new EmbedBuilder();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(Title))
|
|
||||||
embed.WithTitle(Title);
|
|
||||||
if (!string.IsNullOrWhiteSpace(Description))
|
|
||||||
embed.WithDescription(Description);
|
|
||||||
if (Url != null && Uri.IsWellFormedUriString(Url, UriKind.Absolute))
|
|
||||||
embed.WithUrl(Url);
|
|
||||||
embed.WithColor(new Discord.Color(Color));
|
|
||||||
if (Footer != null)
|
|
||||||
embed.WithFooter(Footer.Text,
|
|
||||||
Uri.IsWellFormedUriString(Footer.IconUrl, UriKind.Absolute)
|
|
||||||
? Footer.IconUrl
|
|
||||||
: null);
|
|
||||||
|
|
||||||
if (Thumbnail != null && Uri.IsWellFormedUriString(Thumbnail, UriKind.Absolute))
|
|
||||||
embed.WithThumbnailUrl(Thumbnail);
|
|
||||||
if (Image != null && Uri.IsWellFormedUriString(Image, UriKind.Absolute))
|
|
||||||
embed.WithImageUrl(Image);
|
|
||||||
if (Author != null && !string.IsNullOrWhiteSpace(Author.Name))
|
|
||||||
{
|
|
||||||
if (!Uri.IsWellFormedUriString(Author.IconUrl, UriKind.Absolute))
|
|
||||||
Author.IconUrl = null;
|
|
||||||
if (!Uri.IsWellFormedUriString(Author.Url, UriKind.Absolute))
|
|
||||||
Author.Url = null;
|
|
||||||
|
|
||||||
embed.WithAuthor(Author.Name, Author.IconUrl, Author.Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Fields != null)
|
|
||||||
foreach (var f in Fields)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(f.Name) && !string.IsNullOrWhiteSpace(f.Value))
|
|
||||||
embed.AddField(f.Name, f.Value, f.Inline);
|
|
||||||
}
|
|
||||||
|
|
||||||
return eb.Create(embed);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryParse(string input, out CREmbed embed)
|
|
||||||
{
|
|
||||||
embed = null;
|
|
||||||
if (string.IsNullOrWhiteSpace(input) || !input.Trim().StartsWith('{'))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var crembed = JsonConvert.DeserializeObject<CREmbed>(input);
|
|
||||||
|
|
||||||
if (crembed.Fields != null && crembed.Fields.Length > 0)
|
|
||||||
foreach (var f in crembed.Fields)
|
|
||||||
{
|
|
||||||
f.Name = f.Name.TrimTo(256);
|
|
||||||
f.Value = f.Value.TrimTo(1024);
|
|
||||||
}
|
|
||||||
if (!crembed.IsValid)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
embed = crembed;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CREmbedField
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Value { get; set; }
|
|
||||||
public bool Inline { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CREmbedFooter
|
|
||||||
{
|
|
||||||
public string Text { get; set; }
|
|
||||||
public string IconUrl { get; set; }
|
|
||||||
[JsonProperty("icon_url")]
|
|
||||||
private string Icon_Url { set => IconUrl = value; }
|
|
||||||
}
|
|
||||||
public class CREmbedAuthor
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string IconUrl { get; set; }
|
|
||||||
[JsonProperty("icon_url")]
|
|
||||||
private string Icon_Url { set => IconUrl = value; }
|
|
||||||
public string Url { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@@ -85,34 +85,5 @@ namespace NadekoBot.Common.Replacements
|
|||||||
|
|
||||||
return newEmbedData;
|
return newEmbedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CREmbed Replace(CREmbed embedData)
|
|
||||||
{
|
|
||||||
embedData.PlainText = Replace(embedData.PlainText);
|
|
||||||
embedData.Description = Replace(embedData.Description);
|
|
||||||
embedData.Title = Replace(embedData.Title);
|
|
||||||
embedData.Thumbnail = Replace(embedData.Thumbnail);
|
|
||||||
embedData.Image = Replace(embedData.Image);
|
|
||||||
if (embedData.Author != null)
|
|
||||||
{
|
|
||||||
embedData.Author.Name = Replace(embedData.Author.Name);
|
|
||||||
embedData.Author.IconUrl = Replace(embedData.Author.IconUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (embedData.Fields != null)
|
|
||||||
foreach (var f in embedData.Fields)
|
|
||||||
{
|
|
||||||
f.Name = Replace(f.Name);
|
|
||||||
f.Value = Replace(f.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (embedData.Footer != null)
|
|
||||||
{
|
|
||||||
embedData.Footer.Text = Replace(embedData.Footer.Text);
|
|
||||||
embedData.Footer.IconUrl = Replace(embedData.Footer.IconUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
return embedData;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,140 +1,52 @@
|
|||||||
using AngleSharp;
|
using Discord;
|
||||||
using AngleSharp.Html.Dom;
|
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Common;
|
|
||||||
using NadekoBot.Common.Replacements;
|
using NadekoBot.Common.Replacements;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Services;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions.Extensions
|
namespace NadekoBot.Modules.CustomReactions.Extensions
|
||||||
{
|
{
|
||||||
public static class CustomReactionExtensions
|
public static class CustomReactionExtensions
|
||||||
{
|
{
|
||||||
private static readonly Regex imgRegex = new Regex("%(img|image):(?<tag>.*?)%", RegexOptions.Compiled);
|
private static string ResolveTriggerString(this string str, DiscordSocketClient client)
|
||||||
|
|
||||||
private static Dictionary<Regex, Func<Match, Task<string>>> regexPlaceholders { get; } =
|
|
||||||
new Dictionary<Regex, Func<Match, Task<string>>>()
|
|
||||||
{
|
|
||||||
{
|
|
||||||
imgRegex, async (match) =>
|
|
||||||
{
|
|
||||||
var tag = match.Groups["tag"].ToString();
|
|
||||||
if (string.IsNullOrWhiteSpace(tag))
|
|
||||||
return "";
|
|
||||||
|
|
||||||
var fullQueryLink = $"http://imgur.com/search?q={tag}";
|
|
||||||
var config = Configuration.Default.WithDefaultLoader();
|
|
||||||
using (var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink)
|
|
||||||
.ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var elems = document.QuerySelectorAll("a.image-list-link").ToArray();
|
|
||||||
|
|
||||||
if (!elems.Any())
|
|
||||||
return "";
|
|
||||||
|
|
||||||
var img = (elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Length))?.Children
|
|
||||||
?.FirstOrDefault() as IHtmlImageElement);
|
|
||||||
|
|
||||||
if (img?.Source is null)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
return " " + img.Source.Replace("b.", ".", StringComparison.InvariantCulture) + " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static string ResolveTriggerString(this string str, IUserMessage ctx, DiscordSocketClient client)
|
|
||||||
=> str.Replace("%bot.mention%", client.CurrentUser.Mention, StringComparison.Ordinal);
|
=> str.Replace("%bot.mention%", client.CurrentUser.Mention, StringComparison.Ordinal);
|
||||||
|
|
||||||
private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx,
|
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage ctx,
|
||||||
DiscordSocketClient client, string resolvedTrigger, bool containsAnywhere)
|
DiscordSocketClient client, bool sanitize)
|
||||||
{
|
{
|
||||||
var substringIndex = resolvedTrigger.Length;
|
var channel = cr.DmResponse
|
||||||
if (containsAnywhere)
|
? await ctx.Author.GetOrCreateDMChannelAsync().ConfigureAwait(false)
|
||||||
|
: ctx.Channel;
|
||||||
|
|
||||||
|
var trigger = cr.Trigger.ResolveTriggerString(client);
|
||||||
|
var substringIndex = trigger.Length;
|
||||||
|
if (cr.ContainsAnywhere)
|
||||||
{
|
{
|
||||||
var pos = ctx.Content.AsSpan().GetWordPosition(resolvedTrigger);
|
var pos = ctx.Content.AsSpan().GetWordPosition(trigger);
|
||||||
if (pos == WordPosition.Start)
|
if (pos == WordPosition.Start)
|
||||||
substringIndex += 1;
|
substringIndex += 1;
|
||||||
else if (pos == WordPosition.End)
|
else if (pos == WordPosition.End)
|
||||||
substringIndex = ctx.Content.Length;
|
substringIndex = ctx.Content.Length;
|
||||||
else if (pos == WordPosition.Middle)
|
else if (pos == WordPosition.Middle)
|
||||||
substringIndex += ctx.Content.IndexOf(resolvedTrigger, StringComparison.InvariantCulture);
|
substringIndex += ctx.Content.IndexOf(trigger, StringComparison.InvariantCulture);
|
||||||
}
|
}
|
||||||
|
|
||||||
var canMentionEveryone = (ctx.Author as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
|
var canMentionEveryone = (ctx.Author as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
|
||||||
|
|
||||||
var rep = new ReplacementBuilder()
|
var rep = new ReplacementBuilder()
|
||||||
.WithDefault(ctx.Author, ctx.Channel, (ctx.Channel as ITextChannel)?.Guild as SocketGuild, client)
|
.WithDefault(ctx.Author, ctx.Channel, (ctx.Channel as ITextChannel)?.Guild as SocketGuild, client)
|
||||||
.WithOverride("%target%", () =>
|
.WithOverride("%target%", () => canMentionEveryone
|
||||||
canMentionEveryone
|
? ctx.Content.Substring(substringIndex).Trim()
|
||||||
? ctx.Content.Substring(substringIndex).Trim()
|
: ctx.Content.Substring(substringIndex).Trim().SanitizeMentions(true))
|
||||||
: ctx.Content.Substring(substringIndex).Trim().SanitizeMentions(true))
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
str = rep.Replace(str);
|
var text = SmartText.CreateFrom(cr.Response);
|
||||||
#if !GLOBAL_NADEKO
|
text = rep.Replace(text);
|
||||||
foreach (var ph in regexPlaceholders)
|
|
||||||
{
|
|
||||||
str = await ph.Key.ReplaceAsync(str, ph.Value).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Task<string> ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx,
|
return await channel.SendAsync(text, sanitize);
|
||||||
DiscordSocketClient client, bool containsAnywhere)
|
|
||||||
=> cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client),
|
|
||||||
containsAnywhere);
|
|
||||||
|
|
||||||
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage ctx,
|
|
||||||
DiscordSocketClient client, IEmbedBuilderService eb, bool sanitize)
|
|
||||||
{
|
|
||||||
var channel = cr.DmResponse
|
|
||||||
? await ctx.Author.GetOrCreateDMChannelAsync().ConfigureAwait(false)
|
|
||||||
: ctx.Channel;
|
|
||||||
|
|
||||||
if (CREmbed.TryParse(cr.Response, out CREmbed crembed))
|
|
||||||
{
|
|
||||||
var trigger = cr.Trigger.ResolveTriggerString(ctx, client);
|
|
||||||
var substringIndex = trigger.Length;
|
|
||||||
if (cr.ContainsAnywhere)
|
|
||||||
{
|
|
||||||
var pos = ctx.Content.AsSpan().GetWordPosition(trigger);
|
|
||||||
if (pos == WordPosition.Start)
|
|
||||||
substringIndex += 1;
|
|
||||||
else if (pos == WordPosition.End)
|
|
||||||
substringIndex = ctx.Content.Length;
|
|
||||||
else if (pos == WordPosition.Middle)
|
|
||||||
substringIndex += ctx.Content.IndexOf(trigger, StringComparison.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
var canMentionEveryone = (ctx.Author as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
|
|
||||||
|
|
||||||
var rep = new ReplacementBuilder()
|
|
||||||
.WithDefault(ctx.Author, ctx.Channel, (ctx.Channel as ITextChannel)?.Guild as SocketGuild, client)
|
|
||||||
.WithOverride("%target%", () => canMentionEveryone
|
|
||||||
? ctx.Content.Substring(substringIndex).Trim()
|
|
||||||
: ctx.Content.Substring(substringIndex).Trim().SanitizeMentions(true))
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
rep.Replace(crembed);
|
|
||||||
|
|
||||||
return await channel.EmbedAsync(crembed, eb, sanitize).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await channel
|
|
||||||
.SendMessageAsync(
|
|
||||||
(await cr.ResponseWithContextAsync(ctx, client, cr.ContainsAnywhere).ConfigureAwait(false))
|
|
||||||
.SanitizeMentions(sanitize)).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@@ -429,7 +429,7 @@ namespace NadekoBot.Modules.CustomReactions.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sentMsg = await cr.Send(msg, _client, _eb, false).ConfigureAwait(false);
|
var sentMsg = await cr.Send(msg, _client, false).ConfigureAwait(false);
|
||||||
|
|
||||||
var reactions = cr.GetReactions();
|
var reactions = cr.GetReactions();
|
||||||
foreach (var reaction in reactions)
|
foreach (var reaction in reactions)
|
||||||
|
@@ -68,17 +68,6 @@ namespace NadekoBot.Extensions
|
|||||||
_ => throw new ArgumentOutOfRangeException(nameof(text))
|
_ => throw new ArgumentOutOfRangeException(nameof(text))
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Task<IUserMessage> EmbedAsync(this IMessageChannel channel, CREmbed crEmbed, IEmbedBuilderService eb, bool sanitizeAll = false)
|
|
||||||
{
|
|
||||||
var plainText = sanitizeAll
|
|
||||||
? crEmbed.PlainText?.SanitizeAllMentions() ?? ""
|
|
||||||
: crEmbed.PlainText?.SanitizeMentions() ?? "";
|
|
||||||
|
|
||||||
return channel.SendMessageAsync(plainText, embed: crEmbed.IsEmbedValid
|
|
||||||
? crEmbed.ToEmbed(eb).Build()
|
|
||||||
: null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<ulong> GetGuildIds(this DiscordSocketClient client)
|
public static List<ulong> GetGuildIds(this DiscordSocketClient client)
|
||||||
=> client.Guilds.Select(x => x.Id).ToList();
|
=> client.Guilds.Select(x => x.Id).ToList();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user