Full support for embed arrays in .greet/.bye, .say and other commands which use embeds

- Website to create them is live at eb2.nadeko.bot (it will soon be replacing eb.nadeko.bot)
- Embed arrays don't have a plainText property (it's renamed to 'content')
- Embed arrays use color hex values instead of an integer
- Old embed format will still work
- There shouldn't be any breaking changes
This commit is contained in:
Kwoth
2022-04-26 02:28:51 +02:00
parent 18400dc53a
commit 5d2d74b92a
10 changed files with 185 additions and 105 deletions

View File

@@ -34,69 +34,59 @@ public class Replacer
public SmartText Replace(SmartText data) public SmartText Replace(SmartText data)
=> data switch => data switch
{ {
SmartEmbedText embedData => Replace(embedData), SmartEmbedText embedData => Replace(embedData) with
{
PlainText = Replace(embedData.PlainText),
Color = embedData.Color
},
SmartPlainText plain => Replace(plain), SmartPlainText plain => Replace(plain),
SmartEmbedTextArray arr => Replace(arr), SmartEmbedTextArray arr => Replace(arr),
_ => throw new ArgumentOutOfRangeException(nameof(data), "Unsupported argument type") _ => throw new ArgumentOutOfRangeException(nameof(data), "Unsupported argument type")
}; };
public SmartEmbedTextArray Replace(SmartEmbedTextArray embedArr) private SmartEmbedTextArray Replace(SmartEmbedTextArray embedArr)
=> new() => new()
{ {
Embeds = embedArr.Embeds.Map(Replace), Embeds = embedArr.Embeds.Map(e => Replace(e) with
PlainText = Replace(embedArr.PlainText) {
Color = e.Color
}),
Content = Replace(embedArr.Content)
}; };
public SmartPlainText Replace(SmartPlainText plainText) private SmartPlainText Replace(SmartPlainText plain)
=> Replace(plainText.Text); => Replace(plain.Text);
public SmartEmbedText Replace(SmartEmbedText embedData) private T Replace<T>(T embedData) where T: SmartEmbedTextBase, new()
{ {
var newEmbedData = new SmartEmbedText var newEmbedData = new T
{ {
PlainText = Replace(embedData.PlainText),
Description = Replace(embedData.Description), Description = Replace(embedData.Description),
Title = Replace(embedData.Title), Title = Replace(embedData.Title),
Thumbnail = Replace(embedData.Thumbnail), Thumbnail = Replace(embedData.Thumbnail),
Image = Replace(embedData.Image), Image = Replace(embedData.Image),
Url = Replace(embedData.Url) Url = Replace(embedData.Url),
}; Author = embedData.Author is null
if (embedData.Author is not null) ? null
{ : new()
newEmbedData.Author = new()
{
Name = Replace(embedData.Author.Name),
IconUrl = Replace(embedData.Author.IconUrl)
};
}
if (embedData.Fields is not null)
{
var fields = new List<SmartTextEmbedField>();
foreach (var f in embedData.Fields)
{
var newF = new SmartTextEmbedField
{ {
Name = Replace(f.Name), Name = Replace(embedData.Author.Name),
Value = Replace(f.Value), IconUrl = Replace(embedData.Author.IconUrl)
Inline = f.Inline },
}; Fields = embedData.Fields?.Map(f => new SmartTextEmbedField
fields.Add(newF);
}
newEmbedData.Fields = fields.ToArray();
}
if (embedData.Footer is not null)
{
newEmbedData.Footer = new()
{ {
Text = Replace(embedData.Footer.Text), Name = Replace(f.Name),
IconUrl = Replace(embedData.Footer.IconUrl) Value = Replace(f.Value),
}; Inline = f.Inline
} }),
Footer = embedData.Footer is null
newEmbedData.Color = embedData.Color; ? null
: new()
{
Text = Replace(embedData.Footer.Text),
IconUrl = Replace(embedData.Footer.IconUrl)
}
};
return newEmbedData; return newEmbedData;
} }

View File

@@ -1,20 +1,64 @@
#nullable disable using SixLabors.ImageSharp.PixelFormats;
#nullable disable
namespace NadekoBot; namespace NadekoBot;
public sealed record SmartEmbedText : SmartText public sealed record SmartEmbedArrayElementText : SmartEmbedTextBase
{ {
public string PlainText { get; set; } public string Color { get; init; } = string.Empty;
public string Title { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public string Thumbnail { get; set; }
public string Image { get; set; }
public SmartTextEmbedAuthor Author { get; set; } public SmartEmbedArrayElementText() : base()
public SmartTextEmbedFooter Footer { get; set; } {
public SmartTextEmbedField[] Fields { get; set; }
public uint Color { get; set; } = 7458112; }
public SmartEmbedArrayElementText(IEmbed eb) : base(eb)
{
}
protected override EmbedBuilder GetEmbedInternal()
{
var embed = base.GetEmbedInternal();
return embed.WithColor(Rgba32.ParseHex(Color).ToDiscordColor());
}
}
public sealed record SmartEmbedText : SmartEmbedTextBase
{
public string PlainText { get; init; }
public uint Color { get; init; } = 7458112;
public SmartEmbedText()
{
}
private SmartEmbedText(IEmbed eb, string plainText = null)
: base(eb)
=> (PlainText, Color) = (plainText, eb.Color?.RawValue ?? 0);
public static SmartEmbedText FromEmbed(IEmbed eb, string plainText = null)
=> new(eb, plainText);
protected override EmbedBuilder GetEmbedInternal()
{
var embed = base.GetEmbedInternal();
return embed.WithColor(Color);
}
}
public abstract record SmartEmbedTextBase : SmartText
{
public string Title { get; init; }
public string Description { get; init; }
public string Url { get; init; }
public string Thumbnail { get; init; }
public string Image { get; init; }
public SmartTextEmbedAuthor Author { get; init; }
public SmartTextEmbedFooter Footer { get; init; }
public SmartTextEmbedField[] Fields { get; init; }
public bool IsValid public bool IsValid
=> !string.IsNullOrWhiteSpace(Title) => !string.IsNullOrWhiteSpace(Title)
@@ -26,36 +70,37 @@ public sealed record SmartEmbedText : SmartText
&& (!string.IsNullOrWhiteSpace(Footer.Text) || !string.IsNullOrWhiteSpace(Footer.IconUrl))) && (!string.IsNullOrWhiteSpace(Footer.Text) || !string.IsNullOrWhiteSpace(Footer.IconUrl)))
|| Fields is { Length: > 0 }; || Fields is { Length: > 0 };
public static SmartEmbedText FromEmbed(IEmbed eb, string plainText = null) protected SmartEmbedTextBase()
{ {
var set = new SmartEmbedText
{ }
PlainText = plainText,
Title = eb.Title, protected SmartEmbedTextBase(IEmbed eb)
Description = eb.Description, {
Url = eb.Url, Title = eb.Title;
Thumbnail = eb.Thumbnail?.Url, Description = eb.Description;
Image = eb.Image?.Url, Url = eb.Url;
Author = eb.Author is { } ea Thumbnail = eb.Thumbnail?.Url;
? new() Image = eb.Image?.Url;
{ Author = eb.Author is { } ea
Name = ea.Name, ? new()
Url = ea.Url, {
IconUrl = ea.IconUrl Name = ea.Name,
} Url = ea.Url,
: null, IconUrl = ea.IconUrl
Footer = eb.Footer is { } ef }
? new() : null;
{ Footer = eb.Footer is { } ef
Text = ef.Text, ? new()
IconUrl = ef.IconUrl {
} Text = ef.Text,
: null IconUrl = ef.IconUrl
}; }
: null;
if (eb.Fields.Length > 0) if (eb.Fields.Length > 0)
{ {
set.Fields = eb.Fields.Select(field Fields = eb.Fields.Select(field
=> new SmartTextEmbedField => new SmartTextEmbedField
{ {
Inline = field.Inline, Inline = field.Inline,
@@ -64,14 +109,14 @@ public sealed record SmartEmbedText : SmartText
}) })
.ToArray(); .ToArray();
} }
set.Color = eb.Color?.RawValue ?? 0;
return set;
} }
public EmbedBuilder GetEmbed() public EmbedBuilder GetEmbed()
=> GetEmbedInternal();
protected virtual EmbedBuilder GetEmbedInternal()
{ {
var embed = new EmbedBuilder().WithColor(Color); var embed = new EmbedBuilder();
if (!string.IsNullOrWhiteSpace(Title)) if (!string.IsNullOrWhiteSpace(Title))
embed.WithTitle(Title); embed.WithTitle(Title);

View File

@@ -3,8 +3,8 @@ namespace NadekoBot;
public sealed record SmartEmbedTextArray : SmartText public sealed record SmartEmbedTextArray : SmartText
{ {
public string PlainText { get; set; } public string Content { get; set; }
public SmartEmbedText[] Embeds { get; set; } public SmartEmbedArrayElementText[] Embeds { get; set; }
public bool IsValid public bool IsValid
=> Embeds?.All(x => x.IsValid) ?? false; => Embeds?.All(x => x.IsValid) ?? false;

View File

@@ -30,7 +30,7 @@ public abstract record SmartText
SmartPlainText spt => new SmartPlainText(spt.Text + input), SmartPlainText spt => new SmartPlainText(spt.Text + input),
SmartEmbedTextArray arr => arr with SmartEmbedTextArray arr => arr with
{ {
PlainText = arr.PlainText + input Content = arr.Content + input
}, },
_ => throw new ArgumentOutOfRangeException(nameof(text)) _ => throw new ArgumentOutOfRangeException(nameof(text))
}; };
@@ -45,7 +45,7 @@ public abstract record SmartText
SmartPlainText spt => new SmartPlainText(input + spt.Text), SmartPlainText spt => new SmartPlainText(input + spt.Text),
SmartEmbedTextArray arr => arr with SmartEmbedTextArray arr => arr with
{ {
PlainText = input + arr.PlainText Content = input + arr.Content
}, },
_ => throw new ArgumentOutOfRangeException(nameof(text)) _ => throw new ArgumentOutOfRangeException(nameof(text))
}; };

View File

@@ -256,15 +256,54 @@ public class GreetService : INService, IReadyExecutor
{ {
text = new SmartEmbedText() text = new SmartEmbedText()
{ {
PlainText = pt.Text Description = pt.Text
}; };
} }
else if (text is SmartEmbedText set)
((SmartEmbedText)text).Footer = new()
{ {
Text = $"This message was sent from {user.Guild} server.", text = set with
IconUrl = user.Guild.IconUrl {
}; Footer = CreateFooterSource(user)
};
}
else if (text is SmartEmbedTextArray seta)
{
// if the greet dm message is a text array
var ebElem = seta.Embeds.LastOrDefault();
if (ebElem is null)
{
// if there are no embeds, add an embed with the footer
text = seta with
{
Embeds = new[]
{
new SmartEmbedArrayElementText()
{
Footer = CreateFooterSource(user)
}
}
};
}
else
{
// if the maximum amount of embeds is reached, edit the last embed
if (seta.Embeds.Length >= 10)
{
seta.Embeds[^1] = seta.Embeds[^1] with
{
Footer = CreateFooterSource(user)
};
}
else
{
// if there is less than 10 embeds, add an embed with footer only
seta.Embeds = seta.Embeds.Append(new SmartEmbedArrayElementText()
{
Footer = CreateFooterSource(user)
}).ToArray();
}
}
}
await user.SendAsync(text); await user.SendAsync(text);
} }
@@ -276,6 +315,13 @@ public class GreetService : INService, IReadyExecutor
return true; return true;
} }
private static SmartTextEmbedFooter CreateFooterSource(IGuildUser user)
=> new()
{
Text = $"This message was sent from {user.Guild} server.",
IconUrl = user.Guild.IconUrl
};
private Task OnUserJoined(IGuildUser user) private Task OnUserJoined(IGuildUser user)
{ {
_ = Task.Run(async () => _ = Task.Run(async () =>

View File

@@ -84,13 +84,12 @@ public class PatreonRewardsService : INService, IReadyExecutor
try try
{ {
using var http = _httpFactory.CreateClient(); using var http = _httpFactory.CreateClient();
using var content = new StringContent(string.Empty);
using var res = await http.PostAsync("https://www.patreon.com/api/oauth2/token" using var res = await http.PostAsync("https://www.patreon.com/api/oauth2/token"
+ "?grant_type=refresh_token" + "?grant_type=refresh_token"
+ $"&refresh_token={creds.Patreon.RefreshToken}" + $"&refresh_token={creds.Patreon.RefreshToken}"
+ $"&client_id={creds.Patreon.ClientId}" + $"&client_id={creds.Patreon.ClientId}"
+ $"&client_secret={creds.Patreon.ClientSecret}", + $"&client_secret={creds.Patreon.ClientSecret}",
content); null);
res.EnsureSuccessStatusCode(); res.EnsureSuccessStatusCode();

View File

@@ -8,6 +8,7 @@ public interface IWallet
public Task<bool> Take(long amount, TxData txData); public Task<bool> Take(long amount, TxData txData);
public Task Add(long amount, TxData txData); public Task Add(long amount, TxData txData);
// todo message
public async Task<bool> Transfer( public async Task<bool> Transfer(
long amount, long amount,
IWallet to, IWallet to,

View File

@@ -53,9 +53,8 @@ public sealed class BotCredsProvider : IBotCredsProvider
_config = new ConfigurationBuilder().AddYamlFile(CredsPath, false, true) _config = new ConfigurationBuilder().AddYamlFile(CredsPath, false, true)
.AddEnvironmentVariables("NadekoBot_") .AddEnvironmentVariables("NadekoBot_")
.Build(); .Build();
#if !GLOBAL_NADEKO
_changeToken = ChangeToken.OnChange(() => _config.GetReloadToken(), Reload); _changeToken = ChangeToken.OnChange(() => _config.GetReloadToken(), Reload);
#endif
Reload(); Reload();
} }

View File

@@ -26,7 +26,7 @@ public static class Extensions
SmartEmbedTextArray set => msg.ModifyAsync(x => SmartEmbedTextArray set => msg.ModifyAsync(x =>
{ {
x.Embeds = set.GetEmbedBuilders().Map(eb => eb.Build()); x.Embeds = set.GetEmbedBuilders().Map(eb => eb.Build());
x.Content = set.PlainText?.SanitizeMentions() ?? ""; x.Content = set.Content?.SanitizeMentions() ?? "";
}), }),
SmartPlainText spt => msg.ModifyAsync(x => SmartPlainText spt => msg.ModifyAsync(x =>
{ {

View File

@@ -30,7 +30,7 @@ public static class MessageChannelExtensions
{ {
SmartEmbedText set => channel.SendAsync(set.PlainText, set.GetEmbed().Build(), sanitizeAll: sanitizeAll), SmartEmbedText set => channel.SendAsync(set.PlainText, set.GetEmbed().Build(), sanitizeAll: sanitizeAll),
SmartPlainText st => channel.SendAsync(st.Text, null, sanitizeAll: sanitizeAll), SmartPlainText st => channel.SendAsync(st.Text, null, sanitizeAll: sanitizeAll),
SmartEmbedTextArray arr => channel.SendAsync(arr.PlainText, SmartEmbedTextArray arr => channel.SendAsync(arr.Content,
embeds: arr.GetEmbedBuilders().Map(e => e.Build())), embeds: arr.GetEmbedBuilders().Map(e => e.Build())),
_ => throw new ArgumentOutOfRangeException(nameof(text)) _ => throw new ArgumentOutOfRangeException(nameof(text))
}; };