mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-11-04 16:44:28 -05:00
Fixed some aliases and reworked namespaces
This commit is contained in:
11
src/NadekoBot/_common/_Extensions/DbExtensions.cs
Normal file
11
src/NadekoBot/_common/_Extensions/DbExtensions.cs
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
97
src/NadekoBot/_common/_Extensions/ImagesharpExtensions.cs
Normal file
97
src/NadekoBot/_common/_Extensions/ImagesharpExtensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user