part 3 of the response rework

This commit is contained in:
Kwoth
2024-04-29 21:03:40 +00:00
parent d28c7b500d
commit daa2177559
65 changed files with 508 additions and 625 deletions

View File

@@ -26,7 +26,6 @@ public enum LogType
ChannelUpdated,
UserPresence,
VoicePresence,
VoicePresenceTts,
UserMuted,
UserWarned,

View File

@@ -12,7 +12,6 @@ public sealed class DmContextAdapter : DmContext
private readonly IServiceProvider _services;
private readonly Lazy<IEmbedBuilderService> _ebs;
private readonly Lazy<IBotStrings> _botStrings;
private readonly Lazy<ILocalization> _localization;
@@ -32,14 +31,10 @@ public sealed class DmContextAdapter : DmContext
Bot = ctx.Client.CurrentUser;
_ebs = new(_services.GetRequiredService<IEmbedBuilderService>());
_botStrings = new(_services.GetRequiredService<IBotStrings>);
_localization = new(_services.GetRequiredService<ILocalization>());
}
public override EmbedBuilder Embed()
=> new EmbedBuilder();
public override string GetText(string key, object[]? args = null)
{
var cultureInfo = _localization.Value.GetCultureInfo(default(ulong?));

View File

@@ -5,7 +5,6 @@ public sealed class GuildContextAdapter : GuildContext
{
private readonly IServiceProvider _services;
private readonly ICommandContext _ctx;
private readonly Lazy<IEmbedBuilderService> _ebs;
private readonly Lazy<IBotStrings> _botStrings;
private readonly Lazy<ILocalization> _localization;
@@ -18,9 +17,6 @@ public sealed class GuildContextAdapter : GuildContext
public override IGuildUser User { get; }
public override EmbedBuilder Embed()
=> _ebs.Value.Create();
public GuildContextAdapter(ICommandContext ctx, IMedusaStrings strings, IServiceProvider services)
{
if (ctx.Guild is not IGuild guild || ctx.Channel is not ITextChannel channel)
@@ -33,7 +29,6 @@ public sealed class GuildContextAdapter : GuildContext
Bot = ctx.Client.CurrentUser;
_services = services;
_ebs = new(_services.GetRequiredService<IEmbedBuilderService>());
_botStrings = new(_services.GetRequiredService<IBotStrings>);
_localization = new(_services.GetRequiredService<ILocalization>());

View File

@@ -342,7 +342,6 @@ public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor,
var sis = LoadSneksFromAssembly(safeName, a);
typeReaders = LoadTypeReadersFromAssembly(a, strings);
// todo allow this
if (sis.Count == 0)
{
_kernel.Unload(safeName);

View File

@@ -16,7 +16,6 @@ public abstract class NadekoModule : ModuleBase
public IBotStrings Strings { get; set; }
public ICommandHandler _cmdHandler { get; set; }
public ILocalization _localization { get; set; }
public IEmbedBuilderService _eb { get; set; }
public INadekoInteractionService _inter { get; set; }
public IReplacementService repSvc { get; set; }
public IMessageSenderService _sender { get; set; }
@@ -28,7 +27,7 @@ public abstract class NadekoModule : ModuleBase
=> Context;
public ResponseBuilder Response()
=> new ResponseBuilder(Strings, _eb)
=> new ResponseBuilder(Strings)
.Context(ctx);
protected override void BeforeExecute(CommandInfo command)

View File

@@ -3,5 +3,8 @@
public interface IMessageSenderService
{
ResponseBuilder Response(IMessageChannel channel);
ResponseBuilder Response(ICommandContext hannel);
ResponseBuilder Response(ICommandContext ctx);
ResponseBuilder Response(IUser user);
ResponseBuilder Response(SocketMessageComponent smc);
}

View File

@@ -2,10 +2,6 @@
public static class MessageChannelExtensions
{
public static ResponseBuilder Response(this IMessageChannel channel, IBotStrings bs, IEmbedBuilderService ebs)
=> new ResponseBuilder(bs, ebs)
.Channel(channel);
// main overload that all other send methods reduce to
public static Task<IUserMessage> SendAsync(
this IMessageChannel channel,
@@ -92,7 +88,7 @@ public static class MessageChannelExtensions
this IMessageChannel ch,
EmbedBuilder? embed,
string plainText = "",
IReadOnlyCollection<IEmbedBuilder>? embeds = null,
IReadOnlyCollection<EmbedBuilder>? embeds = null,
NadekoInteraction? inter = null,
IUserMessage? replyTo = null)
=> ch.SendAsync(plainText,

View File

@@ -5,20 +5,27 @@ namespace NadekoBot.Extensions;
public sealed class MessageSenderService : IMessageSenderService, INService
{
private readonly IBotStrings _bs;
private readonly IEmbedBuilderService _ebs;
public MessageSenderService(IBotStrings bs, IEmbedBuilderService ebs)
public MessageSenderService(IBotStrings bs)
{
_bs = bs;
_ebs = ebs;
}
public ResponseBuilder Response(IMessageChannel channel)
=> new ResponseBuilder(_bs, _ebs)
=> new ResponseBuilder(_bs)
.Channel(channel);
public ResponseBuilder Response(ICommandContext ctx)
=> new ResponseBuilder(_bs, _ebs)
=> new ResponseBuilder(_bs)
.Context(ctx);
public ResponseBuilder Response(IUser user)
=> new ResponseBuilder(_bs)
.User(user);
// todo fix interactions
public ResponseBuilder Response(SocketMessageComponent smc)
=> new ResponseBuilder(_bs)
.Channel(smc.Channel);
}

View File

@@ -14,13 +14,14 @@ public sealed class ResponseBuilder
private object[] locParams = [];
private bool shouldReply = true;
private readonly IBotStrings _bs;
private readonly IEmbedBuilderService _ebs;
private EmbedBuilder? embedBuilder = null;
private NadekoInteraction? inter;
private Stream? fileStream = null;
private string? fileName = null;
public ResponseBuilder(IBotStrings bs, IEmbedBuilderService ebs)
public ResponseBuilder(IBotStrings bs)
{
_bs = bs;
_ebs = ebs;
}
private MessageReference? CreateMessageReference(IMessageChannel targetChannel)
@@ -43,8 +44,9 @@ public sealed class ResponseBuilder
failIfNotExists: false);
}
public async Task<IUserMessage> SendAsync()
public async Task<IUserMessage> SendAsync(bool ephemeral = false)
{
// todo use ephemeral in interactions
var targetChannel = InternalResolveChannel() ?? throw new ArgumentNullException(nameof(channel));
var msgReference = CreateMessageReference(targetChannel);
@@ -53,6 +55,15 @@ public sealed class ResponseBuilder
if (sanitizeMentions)
txt = txt?.SanitizeMentions(true);
if (this.fileStream is Stream stream)
return await targetChannel.SendFileAsync(stream,
filename: fileName,
txt,
embed: embed ?? embedBuilder?.Build(),
components: null,
allowedMentions: sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All,
messageReference: msgReference);
return await targetChannel.SendMessageAsync(
txt,
embed: embed ?? embedBuilder?.Build(),
@@ -65,6 +76,7 @@ public sealed class ResponseBuilder
private ulong? InternalResolveGuildId(IMessageChannel? targetChannel)
=> ctx?.Guild?.Id ?? (targetChannel as ITextChannel)?.GuildId;
// todo not good, has to go to the user
private IMessageChannel? InternalResolveChannel()
=> channel ?? ctx?.Channel ?? msg?.Channel;
@@ -188,20 +200,14 @@ public sealed class ResponseBuilder
private IUser? InternalResolveUser()
=> ctx?.User ?? user ?? msg?.Author;
// todo embed colors
public ResponseBuilder Embed(EmbedBuilder eb)
{
embedBuilder = eb;
return this;
}
public ResponseBuilder Embed(Func<IEmbedBuilderService, EmbedBuilder> embedFactory)
{
// todo colors
this.embed = embedFactory(_ebs).Build();
return this;
}
public ResponseBuilder Channel(IMessageChannel channel)
{
this.channel = channel;
@@ -238,9 +244,10 @@ public sealed class ResponseBuilder
return this;
}
public ResponseBuilder Interaction(NadekoInteraction inter)
public ResponseBuilder Interaction(NadekoInteraction? interaction)
{
// todo implement
inter = interaction;
return this;
}
@@ -249,4 +256,11 @@ public sealed class ResponseBuilder
embeds = inputEmbeds;
return this;
}
public ResponseBuilder FileName(Stream fileStream, string fileName)
{
this.fileStream = fileStream;
this.fileName = fileName;
return this;
}
}

View File

@@ -9,11 +9,11 @@ public static class CurrencyServiceExtensions
var wallet = await cs.GetWalletAsync(userId);
return await wallet.GetBalance();
}
// FUTURE should be a transaction
public static async Task<bool> TransferAsync(
this ICurrencyService cs,
IEmbedBuilderService ebs,
IMessageSenderService sender,
IUser from,
IUser to,
long amount,
@@ -29,17 +29,20 @@ public static class CurrencyServiceExtensions
{
try
{
await to.SendConfirmAsync(ebs,
string.IsNullOrWhiteSpace(note)
? $"Received {formattedAmount} from {from} "
: $"Received {formattedAmount} from {from}: {note}");
await sender.Response(to)
.Confirm(string.IsNullOrWhiteSpace(note)
? $"Received {formattedAmount} from {from} "
: $"Received {formattedAmount} from {from}: {note}")
.SendAsync();
}
catch
{
//ignored
}
return true;
}
return false;
}
}
}

View File

@@ -1,79 +1,17 @@
#nullable disable
using NadekoBot.Common.Configs;
// todo remove
namespace NadekoBot.Services;
public interface IEmbedBuilderService
// todo remove
public sealed class DiscordEmbedBuilderWrapper
{
EmbedBuilder Create(ICommandContext ctx = null);
}
// public EmbedBuilder WithColor(EmbedColor color)
// => color switch
// {
// EmbedColor.Ok => Wrap(embed.WithColor(_botConfig.Color.Ok.ToDiscordColor())),
// EmbedColor.Pending => Wrap(embed.WithColor(_botConfig.Color.Pending.ToDiscordColor())),
// EmbedColor.Error => Wrap(embed.WithColor(_botConfig.Color.Error.ToDiscordColor())),
// _ => throw new ArgumentOutOfRangeException(nameof(color), "Unsupported EmbedColor type")
// };
public class EmbedBuilderService : IEmbedBuilderService, INService
{
private readonly BotConfigService _botConfigService;
public EmbedBuilderService(BotConfigService botConfigService)
=> _botConfigService = botConfigService;
public EmbedBuilder Create(ICommandContext ctx = null)
=> new EmbedBuilder();
}
public sealed class DiscordEmbedBuilderWrapper : IEmbedBuilder
{
private readonly BotConfig _botConfig;
private EmbedBuilder embed;
public DiscordEmbedBuilderWrapper(in BotConfig botConfig, EmbedBuilder embed = null)
{
_botConfig = botConfig;
this.embed = embed ?? new EmbedBuilder();
}
public EmbedBuilder WithDescription(string desc)
=> Wrap(embed.WithDescription(desc));
public EmbedBuilder WithTitle(string title)
=> Wrap(embed.WithTitle(title));
public EmbedBuilder AddField(string title, object value, bool isInline = false)
=> Wrap(embed.AddField(title, value, isInline));
public EmbedBuilder WithFooter(string text, string iconUrl = null)
=> Wrap(embed.WithFooter(text, iconUrl));
public EmbedBuilder WithAuthor(string name, string iconUrl = null, string url = null)
=> Wrap(embed.WithAuthor(name, iconUrl, url));
public EmbedBuilder WithUrl(string url)
=> Wrap(embed.WithUrl(url));
public EmbedBuilder WithImageUrl(string url)
=> Wrap(embed.WithImageUrl(url));
public EmbedBuilder WithThumbnailUrl(string url)
=> Wrap(embed.WithThumbnailUrl(url));
public EmbedBuilder WithColor(EmbedColor color)
=> color switch
{
EmbedColor.Ok => Wrap(embed.WithColor(_botConfig.Color.Ok.ToDiscordColor())),
EmbedColor.Pending => Wrap(embed.WithColor(_botConfig.Color.Pending.ToDiscordColor())),
EmbedColor.Error => Wrap(embed.WithColor(_botConfig.Color.Error.ToDiscordColor())),
_ => throw new ArgumentOutOfRangeException(nameof(color), "Unsupported EmbedColor type")
};
public EmbedBuilder WithDiscordColor(Color color)
=> Wrap(embed.WithColor(color));
public Embed Build()
=> embed.Build();
private EmbedBuilder Wrap(EmbedBuilder eb)
{
embed = eb;
return eb;
}
}

View File

@@ -8,7 +8,7 @@ public sealed class CommandsUtilityService : ICommandsUtilityService, INService
private readonly CommandHandler _ch;
private readonly IBotStrings _strings;
private readonly DiscordPermOverrideService _dpos;
private readonly IEmbedBuilderService _eb;
private readonly IMessageSenderService _sender;
private readonly ILocalization _loc;
private readonly IMedusaLoaderService _medusae;
@@ -16,14 +16,14 @@ public sealed class CommandsUtilityService : ICommandsUtilityService, INService
CommandHandler ch,
IBotStrings strings,
DiscordPermOverrideService dpos,
IEmbedBuilderService eb,
IMessageSenderService sender,
ILocalization loc,
IMedusaLoaderService medusae)
{
_ch = ch;
_strings = strings;
_dpos = dpos;
_eb = eb;
_sender = sender;
_loc = loc;
_medusae = medusae;
}

View File

@@ -60,31 +60,34 @@ public static class SocketMessageComponentExtensions
public static Task RespondAsync(
this SocketMessageComponent ch,
IEmbedBuilderService eb,
IMessageSenderService sender,
string text,
MsgType type,
bool ephemeral = false,
NadekoInteraction? inter = null)
{
var builder = new EmbedBuilder().WithDescription(text);
var embed = new EmbedBuilder().WithDescription(text);
builder = (type switch
embed = (type switch
{
MsgType.Error => builder.WithErrorColor(),
MsgType.Ok => builder.WithOkColor(),
MsgType.Pending => builder.WithPendingColor(),
MsgType.Error => embed.WithErrorColor(),
MsgType.Ok => embed.WithOkColor(),
MsgType.Pending => embed.WithPendingColor(),
_ => throw new ArgumentOutOfRangeException(nameof(type))
});
return ch.EmbedAsync(builder, inter: inter, ephemeral: ephemeral);
return sender.Response(ch)
.Embed(embed)
.Interaction(inter)
.SendAsync(ephemeral: ephemeral);
}
// embed title and optional footer overloads
public static Task RespondConfirmAsync(
this SocketMessageComponent smc,
IEmbedBuilderService eb,
IMessageSenderService sender,
string text,
bool ephemeral = false)
=> smc.RespondAsync(eb, text, MsgType.Ok, ephemeral);
=> smc.RespondAsync(sender, text, MsgType.Ok, ephemeral);
}

View File

@@ -4,21 +4,6 @@ namespace NadekoBot.Extensions;
public static class UserExtensions
{
public static async Task<IUserMessage> EmbedAsync(this IUser user, EmbedBuilder embed, string msg = "")
{
var ch = await user.CreateDMChannelAsync();
return await ch.EmbedAsync(embed, msg);
}
public static async Task<IUserMessage> SendAsync(this IUser user, SmartText text, bool sanitizeAll = false)
{
var ch = await user.CreateDMChannelAsync();
return await ch.SendAsync(text, sanitizeAll);
}
public static async Task<IUserMessage> SendConfirmAsync(this IUser user, IEmbedBuilderService eb, string text)
=> await user.SendMessageAsync("", embed: new EmbedBuilder().WithOkColor().WithDescription(text).Build());
// This method is used by everything that fetches the avatar from a user
public static Uri RealAvatarUrl(this IUser usr, ushort size = 256)
=> usr.AvatarId is null ? new(usr.GetDefaultAvatarUrl()) : new Uri(usr.GetAvatarUrl(ImageFormat.Auto, size));