Fixed some aliases and reworked namespaces

This commit is contained in:
Kwoth
2024-04-27 16:03:48 +00:00
parent e0819f760c
commit 812b865add
344 changed files with 3166 additions and 3314 deletions

View File

@@ -0,0 +1,11 @@
using Microsoft.EntityFrameworkCore;
using NadekoBot.Db;
using NadekoBot.Db.Models;
namespace NadekoBot.Extensions;
public static class DbExtensions
{
public static DiscordUser GetOrCreateUser(this DbContext ctx, IUser original, Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>>? includes = null)
=> ctx.GetOrCreateUser(original.Id, original.Username, original.Discriminator, original.AvatarId, includes);
}

View File

@@ -1,4 +1,3 @@
namespace NadekoBot.Extensions;
public static class MessageChannelExtensions
@@ -10,18 +9,35 @@ public static class MessageChannelExtensions
Embed? embed = null,
IReadOnlyCollection<Embed>? embeds = null,
bool sanitizeAll = false,
MessageComponent? components = null)
MessageComponent? components = null,
IUserMessage? replyTo = null)
{
plainText = sanitizeAll
? plainText?.SanitizeAllMentions() ?? ""
: plainText?.SanitizeMentions() ?? "";
var msgReference = CreateMessageReference(channel, replyTo);
return channel.SendMessageAsync(plainText,
embed: embed,
embeds: embeds is null
? null
: embeds as Embed[] ?? embeds.ToArray(),
components: components);
components: components,
messageReference: msgReference);
}
private static MessageReference? CreateMessageReference(IChannel source, IMessage? replyTo)
{
if (replyTo is null)
return null;
if (replyTo.Channel.Id != source.Id)
return null;
return new(replyTo.Id,
replyTo.Channel.Id,
(replyTo.Channel as ITextChannel)?.GuildId,
failIfNotExists: false);
}
public static async Task<IUserMessage> SendAsync(
@@ -30,14 +46,16 @@ public static class MessageChannelExtensions
NadekoInteraction? inter,
Embed? embed = null,
IReadOnlyCollection<Embed>? embeds = null,
bool sanitizeAll = false)
bool sanitizeAll = false,
IUserMessage? replyTo = null)
{
var msg = await channel.SendAsync(plainText,
embed,
embeds,
sanitizeAll,
inter?.CreateComponent());
inter?.CreateComponent(),
replyTo);
if (inter is not null)
await inter.RunAsync(msg);
@@ -47,17 +65,22 @@ public static class MessageChannelExtensions
public static Task<IUserMessage> SendAsync(
this IMessageChannel channel,
SmartText text,
bool sanitizeAll = false)
bool sanitizeAll = false,
IUserMessage? replyTo = null)
=> text switch
{
SmartEmbedText set => channel.SendAsync(set.PlainText,
set.IsValid ? set.GetEmbed().Build() : null,
sanitizeAll: sanitizeAll),
sanitizeAll: sanitizeAll,
replyTo: replyTo),
SmartPlainText st => channel.SendAsync(st.Text,
default(Embed),
sanitizeAll: sanitizeAll),
sanitizeAll: sanitizeAll,
replyTo: replyTo),
SmartEmbedTextArray arr => channel.SendAsync(arr.Content,
embeds: arr.GetEmbedBuilders().Map(e => e.Build())),
embeds: arr.GetEmbedBuilders().Map(e => e.Build()),
sanitizeAll: sanitizeAll,
replyTo: replyTo),
_ => throw new ArgumentOutOfRangeException(nameof(text))
};
@@ -66,18 +89,21 @@ public static class MessageChannelExtensions
IEmbedBuilder? embed,
string plainText = "",
IReadOnlyCollection<IEmbedBuilder>? embeds = null,
NadekoInteraction? inter = null)
NadekoInteraction? inter = null,
IUserMessage? replyTo = null)
=> ch.SendAsync(plainText,
inter,
embed: embed?.Build(),
embeds: embeds?.Map(x => x.Build()));
embeds: embeds?.Map(x => x.Build()),
replyTo: replyTo);
public static Task<IUserMessage> SendAsync(
this IMessageChannel ch,
IEmbedBuilderService eb,
string text,
MsgType type,
NadekoInteraction? inter = null)
NadekoInteraction? inter = null,
IUserMessage? replyTo = null)
{
var builder = eb.Create().WithDescription(text);
@@ -89,12 +115,12 @@ public static class MessageChannelExtensions
_ => throw new ArgumentOutOfRangeException(nameof(type))
});
return ch.EmbedAsync(builder, inter: inter);
return ch.EmbedAsync(builder, inter: inter, replyTo: replyTo);
}
public static Task<IUserMessage> SendConfirmAsync(this IMessageChannel ch, IEmbedBuilderService eb, string text)
=> ch.SendAsync(eb, text, MsgType.Ok);
public static Task<IUserMessage> SendAsync(
this IMessageChannel ch,
IEmbedBuilderService eb,
@@ -121,12 +147,12 @@ public static class MessageChannelExtensions
MsgType.Pending => embed.WithPendingColor(),
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
return ch.EmbedAsync(embed);
}
// embed title and optional footer overloads
public static Task<IUserMessage> SendConfirmAsync(
this IMessageChannel ch,
IEmbedBuilderService eb,
@@ -135,7 +161,7 @@ public static class MessageChannelExtensions
string? url = null,
string? footer = null)
=> ch.SendAsync(eb, MsgType.Ok, title, text, url, footer);
public static Task<IUserMessage> SendErrorAsync(
this IMessageChannel ch,
IEmbedBuilderService eb,
@@ -144,7 +170,7 @@ public static class MessageChannelExtensions
string? url = null,
string? footer = null)
=> ch.SendAsync(eb, MsgType.Error, title, text, url, footer);
// regular send overloads
public static Task<IUserMessage> SendErrorAsync(this IMessageChannel ch, IEmbedBuilderService eb, string text)
=> ch.SendAsync(eb, text, MsgType.Error);
@@ -164,7 +190,7 @@ public static class MessageChannelExtensions
private const string BUTTON_LEFT = "BUTTON_LEFT";
private const string BUTTON_RIGHT = "BUTTON_RIGHT";
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>");
private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>");
@@ -181,7 +207,7 @@ public static class MessageChannelExtensions
totalElements,
itemsPerPage,
addPaginatedFooter);
public static async Task SendPaginatedConfirmAsync<T>(
this ICommandContext ctx,
int currentPage,
@@ -192,23 +218,24 @@ public static class MessageChannelExtensions
bool addPaginatedFooter = true)
{
var lastPage = (totalElements - 1) / itemsPerPage;
var embed = await pageFunc(currentPage);
if (addPaginatedFooter)
embed.AddPaginatedFooter(currentPage, lastPage);
SimpleInteraction<T>? maybeInter = null;
async Task<ComponentBuilder> GetComponentBuilder()
{
var cb = new ComponentBuilder();
cb.WithButton(new ButtonBuilder()
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_LEFT)
.WithDisabled(lastPage == 0)
.WithEmote(_arrowLeft)
.WithDisabled(currentPage <= 0));
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_LEFT)
.WithDisabled(lastPage == 0)
.WithEmote(_arrowLeft)
.WithDisabled(currentPage <= 0));
if (interFactory is not null)
{
@@ -219,10 +246,10 @@ public static class MessageChannelExtensions
}
cb.WithButton(new ButtonBuilder()
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_RIGHT)
.WithDisabled(lastPage == 0 || currentPage >= lastPage)
.WithEmote(_arrowRight));
.WithStyle(ButtonStyle.Primary)
.WithCustomId(BUTTON_RIGHT)
.WithDisabled(lastPage == 0 || currentPage >= lastPage)
.WithEmote(_arrowRight));
return cb;
}
@@ -232,7 +259,7 @@ public static class MessageChannelExtensions
var toSend = await pageFunc(currentPage);
if (addPaginatedFooter)
toSend.AddPaginatedFooter(currentPage, lastPage);
var component = (await GetComponentBuilder()).Build();
await smc.ModifyOriginalResponseAsync(x =>
@@ -241,9 +268,9 @@ public static class MessageChannelExtensions
x.Components = component;
});
}
var component = (await GetComponentBuilder()).Build();
var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component);
var msg = await ctx.Channel.SendAsync(null, embed: embed.Build(), components: component, replyTo: ctx.Message);
async Task OnInteractionAsync(SocketInteraction si)
{
@@ -271,7 +298,7 @@ public static class MessageChannelExtensions
{
if (currentPage >= lastPage)
return;
++currentPage;
_ = UpdatePageAsync(smc);
}
@@ -297,14 +324,14 @@ public static class MessageChannelExtensions
await Task.Delay(30_000);
client.InteractionCreated -= OnInteractionAsync;
await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
}
private static readonly Emoji _okEmoji = new Emoji("✅");
private static readonly Emoji _warnEmoji = new Emoji("⚠️");
private static readonly Emoji _errorEmoji = new Emoji("❌");
public static Task ReactAsync(this ICommandContext ctx, MsgType type)
{
var emoji = type switch

View File

@@ -0,0 +1,97 @@
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Color = Discord.Color;
namespace NadekoBot.Extensions;
public static class ImagesharpExtensions
{
// https://github.com/SixLabors/Samples/blob/master/ImageSharp/AvatarWithRoundedCorner/Program.cs
public static IImageProcessingContext ApplyRoundedCorners(this IImageProcessingContext ctx, float cornerRadius)
{
var size = ctx.GetCurrentSize();
var corners = BuildCorners(size.Width, size.Height, cornerRadius);
ctx.SetGraphicsOptions(new GraphicsOptions
{
Antialias = true,
// enforces that any part of this shape that has color is punched out of the background
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
});
foreach (var c in corners)
ctx = ctx.Fill(SixLabors.ImageSharp.Color.Red, c);
return ctx;
}
private static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
{
// first create a square
var rect = new RectangularPolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
// then cut out of the square a circle so we are left with a corner
var cornerTopLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
// corner is now a corner shape positions top left
//lets make 3 more positioned correctly, we can do that by translating the original around the center of the image
var rightPos = imageWidth - cornerTopLeft.Bounds.Width + 1;
var bottomPos = imageHeight - cornerTopLeft.Bounds.Height + 1;
// move it across the width of the image - the width of the shape
var cornerTopRight = cornerTopLeft.RotateDegree(90).Translate(rightPos, 0);
var cornerBottomLeft = cornerTopLeft.RotateDegree(-90).Translate(0, bottomPos);
var cornerBottomRight = cornerTopLeft.RotateDegree(180).Translate(rightPos, bottomPos);
return new PathCollection(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
}
public static Color ToDiscordColor(this Rgba32 color)
=> new(color.R, color.G, color.B);
public static MemoryStream ToStream(this Image<Rgba32> img, IImageFormat? format = null)
{
var imageStream = new MemoryStream();
if (format?.Name == "GIF")
img.SaveAsGif(imageStream);
else
{
img.SaveAsPng(imageStream,
new()
{
ColorType = PngColorType.RgbWithAlpha,
CompressionLevel = PngCompressionLevel.DefaultCompression
});
}
imageStream.Position = 0;
return imageStream;
}
public static async Task<MemoryStream> ToStreamAsync(this Image<Rgba32> img, IImageFormat? format = null)
{
var imageStream = new MemoryStream();
if (format?.Name == "GIF")
{
await img.SaveAsGifAsync(imageStream);
}
else
{
await img.SaveAsPngAsync(imageStream,
new PngEncoder()
{
ColorType = PngColorType.RgbWithAlpha,
CompressionLevel = PngCompressionLevel.DefaultCompression
});
}
imageStream.Position = 0;
return imageStream;
}
}