mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
part 3 of the response rework
This commit is contained in:
@@ -26,7 +26,6 @@ public enum LogType
|
||||
ChannelUpdated,
|
||||
UserPresence,
|
||||
VoicePresence,
|
||||
VoicePresenceTts,
|
||||
UserMuted,
|
||||
UserWarned,
|
||||
|
||||
|
@@ -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?));
|
||||
|
@@ -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>());
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
@@ -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,
|
||||
|
@@ -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);
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
@@ -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));
|
||||
|
Reference in New Issue
Block a user