mirror of
				https://gitlab.com/Kwoth/nadekobot.git
				synced 2025-11-04 00:34:26 -05:00 
			
		
		
		
	Greatly unboilerplated and simplified nadeko interaction button construction
This commit is contained in:
		@@ -0,0 +1,8 @@
 | 
			
		||||
namespace NadekoBot;
 | 
			
		||||
 | 
			
		||||
public interface INadekoInteractionService
 | 
			
		||||
{
 | 
			
		||||
    public NadekoInteraction Create<T>(
 | 
			
		||||
        ulong userId,
 | 
			
		||||
        SimpleInteraction<T> inter);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
namespace NadekoBot;
 | 
			
		||||
 | 
			
		||||
public sealed class NadekoButtonActionInteraction : NadekoButtonOwnInteraction
 | 
			
		||||
{
 | 
			
		||||
    private readonly NadekoInteractionData _data;
 | 
			
		||||
    private readonly Func<SocketMessageComponent, Task> _action;
 | 
			
		||||
 | 
			
		||||
    public NadekoButtonActionInteraction(
 | 
			
		||||
        DiscordSocketClient client,
 | 
			
		||||
        ulong authorId,
 | 
			
		||||
        NadekoInteractionData data,
 | 
			
		||||
        Func<SocketMessageComponent, Task> action
 | 
			
		||||
    )
 | 
			
		||||
        : base(client, authorId)
 | 
			
		||||
    {
 | 
			
		||||
        _data = data;
 | 
			
		||||
        _action = action;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected override string Name
 | 
			
		||||
        => _data.CustomId;
 | 
			
		||||
    protected override IEmote Emote
 | 
			
		||||
        => _data.Emote;
 | 
			
		||||
    protected override string? Text
 | 
			
		||||
        => _data.Text;
 | 
			
		||||
 | 
			
		||||
    public override Task ExecuteOnActionAsync(SocketMessageComponent smc)
 | 
			
		||||
        => _action(smc);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +1,30 @@
 | 
			
		||||
namespace NadekoBot;
 | 
			
		||||
 | 
			
		||||
public abstract class NadekoButtonInteraction
 | 
			
		||||
public sealed class NadekoInteraction
 | 
			
		||||
{
 | 
			
		||||
    // improvements:
 | 
			
		||||
    //  - state in OnAction
 | 
			
		||||
    //  - configurable delay
 | 
			
		||||
    //  - 
 | 
			
		||||
    protected abstract string Name { get; }
 | 
			
		||||
    protected abstract IEmote Emote { get; }
 | 
			
		||||
    protected virtual string? Text { get; } = null;
 | 
			
		||||
 | 
			
		||||
    private readonly ulong _authorId;
 | 
			
		||||
    private readonly ButtonBuilder _button;
 | 
			
		||||
    private readonly Func<SocketMessageComponent, Task> _onClick;
 | 
			
		||||
    private readonly bool _onlyAuthor;
 | 
			
		||||
    public DiscordSocketClient Client { get; }
 | 
			
		||||
 | 
			
		||||
    protected readonly TaskCompletionSource<bool> _interactionCompletedSource;
 | 
			
		||||
    private readonly TaskCompletionSource<bool> _interactionCompletedSource;
 | 
			
		||||
 | 
			
		||||
    protected IUserMessage message = null!;
 | 
			
		||||
    private IUserMessage message = null!;
 | 
			
		||||
 | 
			
		||||
    protected NadekoButtonInteraction(DiscordSocketClient client)
 | 
			
		||||
    public NadekoInteraction(DiscordSocketClient client,
 | 
			
		||||
        ulong authorId,
 | 
			
		||||
        ButtonBuilder button,
 | 
			
		||||
        Func<SocketMessageComponent, Task> onClick,
 | 
			
		||||
        bool onlyAuthor)
 | 
			
		||||
    {
 | 
			
		||||
        Client = client;
 | 
			
		||||
        _authorId = authorId;
 | 
			
		||||
        _button = button;
 | 
			
		||||
        _onClick = onClick;
 | 
			
		||||
        _onlyAuthor = onlyAuthor;
 | 
			
		||||
        _interactionCompletedSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
 | 
			
		||||
        
 | 
			
		||||
        Client = client;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async Task RunAsync(IUserMessage msg)
 | 
			
		||||
@@ -27,13 +32,12 @@ public abstract class NadekoButtonInteraction
 | 
			
		||||
        message = msg;
 | 
			
		||||
 | 
			
		||||
        Client.InteractionCreated += OnInteraction;
 | 
			
		||||
        await Task.WhenAny(Task.Delay(10_000), _interactionCompletedSource.Task);
 | 
			
		||||
        await Task.WhenAny(Task.Delay(15_000), _interactionCompletedSource.Task);
 | 
			
		||||
        Client.InteractionCreated -= OnInteraction;
 | 
			
		||||
 | 
			
		||||
        await msg.ModifyAsync(m => m.Components = new ComponentBuilder().Build());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract ValueTask<bool> Validate(SocketMessageComponent smc);
 | 
			
		||||
    
 | 
			
		||||
    private async Task OnInteraction(SocketInteraction arg)
 | 
			
		||||
    {
 | 
			
		||||
        if (arg is not SocketMessageComponent smc)
 | 
			
		||||
@@ -42,14 +46,11 @@ public abstract class NadekoButtonInteraction
 | 
			
		||||
        if (smc.Message.Id != message.Id)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (smc.Data.CustomId != Name)
 | 
			
		||||
        if (_onlyAuthor && smc.User.Id != _authorId)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (!await Validate(smc))
 | 
			
		||||
        {
 | 
			
		||||
            await smc.DeferAsync();
 | 
			
		||||
        if (smc.Data.CustomId != _button.CustomId)
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _ = Task.Run(async () =>
 | 
			
		||||
        {
 | 
			
		||||
@@ -66,18 +67,14 @@ public abstract class NadekoButtonInteraction
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public virtual MessageComponent CreateComponent()
 | 
			
		||||
    public MessageComponent CreateComponent()
 | 
			
		||||
    {
 | 
			
		||||
        var comp = new ComponentBuilder()
 | 
			
		||||
            .WithButton(GetButtonBuilder());
 | 
			
		||||
            .WithButton(_button);
 | 
			
		||||
 | 
			
		||||
        return comp.Build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ButtonBuilder GetButtonBuilder()
 | 
			
		||||
        => new ButtonBuilder(style: ButtonStyle.Secondary, emote: Emote, customId: Name, label: Text);
 | 
			
		||||
 | 
			
		||||
    public abstract Task ExecuteOnActionAsync(SocketMessageComponent smc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// this is all so wrong ...
 | 
			
		||||
    public Task ExecuteOnActionAsync(SocketMessageComponent smc)
 | 
			
		||||
        => _onClick(smc);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
// namespace NadekoBot;
 | 
			
		||||
//
 | 
			
		||||
// public class NadekoButtonInteractionArray : NadekoButtonInteraction
 | 
			
		||||
// {
 | 
			
		||||
//     private readonly ButtonBuilder[] _bbs;
 | 
			
		||||
//     private readonly NadekoButtonInteraction[] _inters;
 | 
			
		||||
//
 | 
			
		||||
//     public NadekoButtonInteractionArray(params NadekoButtonInteraction[] inters)
 | 
			
		||||
//         : base(inters[0].Client)
 | 
			
		||||
//     {
 | 
			
		||||
//         _inters = inters;
 | 
			
		||||
//         _bbs = inters.Map(x => x.GetButtonBuilder());
 | 
			
		||||
//     }
 | 
			
		||||
//
 | 
			
		||||
//     protected override string Name
 | 
			
		||||
//         => throw new NotSupportedException();
 | 
			
		||||
//     protected override IEmote Emote
 | 
			
		||||
//         => throw new NotSupportedException();
 | 
			
		||||
//
 | 
			
		||||
//     protected override ValueTask<bool> Validate(SocketMessageComponent smc)
 | 
			
		||||
//         => new(true);
 | 
			
		||||
//
 | 
			
		||||
//     public override Task ExecuteOnActionAsync(SocketMessageComponent smc)
 | 
			
		||||
//     {
 | 
			
		||||
//         for (var i = 0; i < _bbs.Length; i++)
 | 
			
		||||
//         {
 | 
			
		||||
//             if (_bbs[i].CustomId == smc.Data.CustomId)
 | 
			
		||||
//                 return _inters[i].ExecuteOnActionAsync(smc);
 | 
			
		||||
//         }
 | 
			
		||||
//
 | 
			
		||||
//         return Task.CompletedTask;
 | 
			
		||||
//     }
 | 
			
		||||
//
 | 
			
		||||
//     public override MessageComponent CreateComponent()
 | 
			
		||||
//     {
 | 
			
		||||
//         var comp = new ComponentBuilder();
 | 
			
		||||
//
 | 
			
		||||
//         foreach (var bb in _bbs)
 | 
			
		||||
//             comp.WithButton(bb);
 | 
			
		||||
//         
 | 
			
		||||
//         return comp.Build();
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
@@ -1,42 +0,0 @@
 | 
			
		||||
namespace NadekoBot;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Builder class for NadekoInteractions
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class NadekoInteractionBuilder
 | 
			
		||||
{
 | 
			
		||||
    private NadekoInteractionData? iData;
 | 
			
		||||
    private Func<SocketMessageComponent, Task>? action;
 | 
			
		||||
    // private bool isOwn;
 | 
			
		||||
 | 
			
		||||
    public NadekoInteractionBuilder WithData<T>(in T data)
 | 
			
		||||
        where T : NadekoInteractionData
 | 
			
		||||
    {
 | 
			
		||||
        iData = data;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // public NadekoOwnInteractionBuiler WithIsOwn(bool isOwn = true)
 | 
			
		||||
    // {
 | 
			
		||||
    //     this.isOwn = isOwn;
 | 
			
		||||
    //     return this;
 | 
			
		||||
    
 | 
			
		||||
    // }
 | 
			
		||||
    
 | 
			
		||||
    public NadekoInteractionBuilder WithAction(in Func<SocketMessageComponent, Task> fn)
 | 
			
		||||
    {
 | 
			
		||||
        this.action = fn;
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public NadekoButtonActionInteraction Build(DiscordSocketClient client, ulong userId)
 | 
			
		||||
    {
 | 
			
		||||
        if (iData is null)
 | 
			
		||||
            throw new InvalidOperationException("You have to specify the data before building the interaction");
 | 
			
		||||
 | 
			
		||||
        if (action is null)
 | 
			
		||||
            throw new InvalidOperationException("You have to specify the action before building the interaction");
 | 
			
		||||
 | 
			
		||||
        return new(client, userId, iData, action);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								src/NadekoBot/Common/Interaction/NadekoInteractionService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/NadekoBot/Common/Interaction/NadekoInteractionService.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
namespace NadekoBot;
 | 
			
		||||
 | 
			
		||||
public class NadekoInteractionService : INadekoInteractionService, INService
 | 
			
		||||
{
 | 
			
		||||
    private readonly DiscordSocketClient _client;
 | 
			
		||||
 | 
			
		||||
    public NadekoInteractionService(DiscordSocketClient client)
 | 
			
		||||
    {
 | 
			
		||||
        _client = client;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public NadekoInteraction Create<T>(
 | 
			
		||||
        ulong userId,
 | 
			
		||||
        SimpleInteraction<T> inter)
 | 
			
		||||
        => new NadekoInteraction(_client,
 | 
			
		||||
            userId,
 | 
			
		||||
            inter.Button,
 | 
			
		||||
            inter.TriggerAsync,
 | 
			
		||||
            onlyAuthor: true);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
namespace NadekoBot;
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Interaction which only the author can use
 | 
			
		||||
/// </summary>
 | 
			
		||||
public abstract class NadekoButtonOwnInteraction : NadekoButtonInteraction
 | 
			
		||||
{
 | 
			
		||||
    protected readonly ulong _authorId;
 | 
			
		||||
 | 
			
		||||
    protected NadekoButtonOwnInteraction(DiscordSocketClient client, ulong authorId) : base(client)
 | 
			
		||||
        => _authorId = authorId;
 | 
			
		||||
 | 
			
		||||
    protected override ValueTask<bool> Validate(SocketMessageComponent smc)
 | 
			
		||||
        => new(smc.User.Id == _authorId);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
namespace NadekoBot.Common;
 | 
			
		||||
 | 
			
		||||
public abstract class NInteraction
 | 
			
		||||
{
 | 
			
		||||
    private readonly DiscordSocketClient _client;
 | 
			
		||||
    private readonly ulong _userId;
 | 
			
		||||
    private readonly Func<SocketMessageComponent, Task> _action;
 | 
			
		||||
 | 
			
		||||
    protected abstract NadekoInteractionData Data { get; }
 | 
			
		||||
 | 
			
		||||
    public NInteraction(
 | 
			
		||||
        DiscordSocketClient client,
 | 
			
		||||
        ulong userId,
 | 
			
		||||
        Func<SocketMessageComponent, Task> action)
 | 
			
		||||
    {
 | 
			
		||||
        _client = client;
 | 
			
		||||
        _userId = userId;
 | 
			
		||||
        _action = action;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public NadekoButtonInteraction GetInteraction()
 | 
			
		||||
        => new NadekoInteractionBuilder()
 | 
			
		||||
           .WithData(Data)
 | 
			
		||||
           .WithAction(_action)
 | 
			
		||||
           .Build(_client, _userId);
 | 
			
		||||
}
 | 
			
		||||
@@ -18,6 +18,7 @@ public abstract class NadekoModule : ModuleBase
 | 
			
		||||
    public CommandHandler _cmdHandler { get; set; }
 | 
			
		||||
    public ILocalization _localization { get; set; }
 | 
			
		||||
    public IEmbedBuilderService _eb { get; set; }
 | 
			
		||||
    public INadekoInteractionService _inter { get; set; }
 | 
			
		||||
 | 
			
		||||
    protected string prefix
 | 
			
		||||
        => _cmdHandler.GetPrefix(ctx.Guild);
 | 
			
		||||
@@ -36,7 +37,7 @@ public abstract class NadekoModule : ModuleBase
 | 
			
		||||
        string error,
 | 
			
		||||
        string url = null,
 | 
			
		||||
        string footer = null, 
 | 
			
		||||
        NadekoButtonInteraction inter = null)
 | 
			
		||||
        NadekoInteraction inter = null)
 | 
			
		||||
        => ctx.Channel.SendErrorAsync(_eb, title, error, url, footer);
 | 
			
		||||
    
 | 
			
		||||
    public Task<IUserMessage> SendConfirmAsync(
 | 
			
		||||
@@ -47,32 +48,32 @@ public abstract class NadekoModule : ModuleBase
 | 
			
		||||
        => ctx.Channel.SendConfirmAsync(_eb, title, text, url, footer);
 | 
			
		||||
 | 
			
		||||
    // 
 | 
			
		||||
    public Task<IUserMessage> SendErrorAsync(string text, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> SendErrorAsync(string text, NadekoInteraction inter = null)
 | 
			
		||||
        => ctx.Channel.SendAsync(_eb, text, MessageType.Error, inter);
 | 
			
		||||
    public Task<IUserMessage> SendConfirmAsync(string text, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> SendConfirmAsync(string text, NadekoInteraction inter = null)
 | 
			
		||||
        => ctx.Channel.SendAsync(_eb, text, MessageType.Ok, inter);
 | 
			
		||||
    public Task<IUserMessage> SendPendingAsync(string text, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> SendPendingAsync(string text, NadekoInteraction inter = null)
 | 
			
		||||
        => ctx.Channel.SendAsync(_eb, text, MessageType.Pending, inter);
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    // localized normal
 | 
			
		||||
    public Task<IUserMessage> ErrorLocalizedAsync(LocStr str, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> ErrorLocalizedAsync(LocStr str, NadekoInteraction inter = null)
 | 
			
		||||
        => SendErrorAsync(GetText(str), inter);
 | 
			
		||||
 | 
			
		||||
    public Task<IUserMessage> PendingLocalizedAsync(LocStr str, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> PendingLocalizedAsync(LocStr str, NadekoInteraction inter = null)
 | 
			
		||||
        => SendPendingAsync(GetText(str), inter);
 | 
			
		||||
 | 
			
		||||
    public Task<IUserMessage> ConfirmLocalizedAsync(LocStr str, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> ConfirmLocalizedAsync(LocStr str, NadekoInteraction inter = null)
 | 
			
		||||
        => SendConfirmAsync(GetText(str), inter);
 | 
			
		||||
 | 
			
		||||
    // localized replies
 | 
			
		||||
    public Task<IUserMessage> ReplyErrorLocalizedAsync(LocStr str, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> ReplyErrorLocalizedAsync(LocStr str, NadekoInteraction inter = null)
 | 
			
		||||
        => SendErrorAsync($"{Format.Bold(ctx.User.ToString())} {GetText(str)}", inter);
 | 
			
		||||
 | 
			
		||||
    public Task<IUserMessage> ReplyPendingLocalizedAsync(LocStr str, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> ReplyPendingLocalizedAsync(LocStr str, NadekoInteraction inter = null)
 | 
			
		||||
        => SendPendingAsync($"{Format.Bold(ctx.User.ToString())} {GetText(str)}", inter);
 | 
			
		||||
 | 
			
		||||
    public Task<IUserMessage> ReplyConfirmLocalizedAsync(LocStr str, NadekoButtonInteraction inter = null)
 | 
			
		||||
    public Task<IUserMessage> ReplyConfirmLocalizedAsync(LocStr str, NadekoInteraction inter = null)
 | 
			
		||||
        => SendConfirmAsync($"{Format.Bold(ctx.User.ToString())} {GetText(str)}", inter);
 | 
			
		||||
 | 
			
		||||
    public async Task<bool> PromptUserConfirmAsync(IEmbedBuilder embed)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
#nullable disable
 | 
			
		||||
namespace NadekoBot.Modules.Gambling;
 | 
			
		||||
 | 
			
		||||
public class CashInteraction : NInteraction
 | 
			
		||||
{
 | 
			
		||||
    protected override NadekoInteractionData Data
 | 
			
		||||
        => new NadekoInteractionData(new Emoji("🏦"), "cash:bank_show_balance");
 | 
			
		||||
 | 
			
		||||
    public CashInteraction(DiscordSocketClient client, ulong userId, Func<SocketMessageComponent, Task> action)
 | 
			
		||||
        : base(client, userId, action)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -99,39 +99,20 @@ public partial class Gambling : GamblingModule<GamblingService>
 | 
			
		||||
        PrettyName = "Timely"
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public class RemindMeInteraction : NInteraction
 | 
			
		||||
    private async Task RemindTimelyAction(SocketMessageComponent smc, DateTime when)
 | 
			
		||||
    {
 | 
			
		||||
        public RemindMeInteraction(
 | 
			
		||||
            [NotNull] DiscordSocketClient client,
 | 
			
		||||
            ulong userId,
 | 
			
		||||
            [NotNull] Func<SocketMessageComponent, Task> action)
 | 
			
		||||
            : base(client, userId, action)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
        var tt = TimestampTag.FromDateTime(when, TimestampTagStyles.Relative);
 | 
			
		||||
 | 
			
		||||
        protected override NadekoInteractionData Data
 | 
			
		||||
            => new NadekoInteractionData(
 | 
			
		||||
                Emote: Emoji.Parse("⏰"),
 | 
			
		||||
                CustomId: "timely:remind_me",
 | 
			
		||||
                Text: "Remind me"
 | 
			
		||||
            );
 | 
			
		||||
        await _remind.AddReminderAsync(ctx.User.Id,
 | 
			
		||||
            ctx.User.Id,
 | 
			
		||||
            ctx.Guild.Id,
 | 
			
		||||
            true,
 | 
			
		||||
            when,
 | 
			
		||||
            GetText(strs.timely_time));
 | 
			
		||||
 | 
			
		||||
        await smc.RespondConfirmAsync(_eb, GetText(strs.remind_timely(tt)), ephemeral: true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Func<SocketMessageComponent, Task> RemindTimelyAction(DateTime when)
 | 
			
		||||
        => async smc =>
 | 
			
		||||
        {
 | 
			
		||||
            var tt = TimestampTag.FromDateTime(when, TimestampTagStyles.Relative);
 | 
			
		||||
 | 
			
		||||
            await _remind.AddReminderAsync(ctx.User.Id,
 | 
			
		||||
                ctx.User.Id,
 | 
			
		||||
                ctx.Guild.Id,
 | 
			
		||||
                true,
 | 
			
		||||
                when,
 | 
			
		||||
                GetText(strs.timely_time));
 | 
			
		||||
 | 
			
		||||
            await smc.RespondConfirmAsync(_eb, GetText(strs.remind_timely(tt)), ephemeral: true);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    [Cmd]
 | 
			
		||||
    public async Task Timely()
 | 
			
		||||
    {
 | 
			
		||||
@@ -157,11 +138,17 @@ public partial class Gambling : GamblingModule<GamblingService>
 | 
			
		||||
 | 
			
		||||
        await _cs.AddAsync(ctx.User.Id, val, new("timely", "claim"));
 | 
			
		||||
 | 
			
		||||
        var inter = new RemindMeInteraction(_client,
 | 
			
		||||
            ctx.User.Id,
 | 
			
		||||
            RemindTimelyAction(DateTime.UtcNow.Add(TimeSpan.FromHours(period))));
 | 
			
		||||
        
 | 
			
		||||
        await ReplyConfirmLocalizedAsync(strs.timely(N(val), period), inter.GetInteraction());
 | 
			
		||||
        var inter = _inter
 | 
			
		||||
            .Create(ctx.User.Id,
 | 
			
		||||
                new SimpleInteraction<DateTime>(
 | 
			
		||||
                    new ButtonBuilder(
 | 
			
		||||
                        label: "Remind me",
 | 
			
		||||
                        emote: Emoji.Parse("⏰"),
 | 
			
		||||
                        customId: "timely:remind_me"),
 | 
			
		||||
                    RemindTimelyAction,
 | 
			
		||||
                    DateTime.UtcNow.Add(TimeSpan.FromHours(period))));
 | 
			
		||||
 | 
			
		||||
        await ReplyConfirmLocalizedAsync(strs.timely(N(val), period), inter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Cmd]
 | 
			
		||||
@@ -362,7 +349,7 @@ public partial class Gambling : GamblingModule<GamblingService>
 | 
			
		||||
        await ReplyConfirmLocalizedAsync(strs.has(Format.Code(userId.ToString()), cur));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async Task BankAction(SocketMessageComponent smc)
 | 
			
		||||
    private async Task BankAction(SocketMessageComponent smc, object _)
 | 
			
		||||
    {
 | 
			
		||||
        var balance = await _bank.GetBalanceAsync(ctx.User.Id);
 | 
			
		||||
 | 
			
		||||
@@ -372,8 +359,12 @@ public partial class Gambling : GamblingModule<GamblingService>
 | 
			
		||||
              .Pipe(text => smc.RespondConfirmAsync(_eb, text, ephemeral: true));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private NadekoButtonInteraction CreateCashInteraction()
 | 
			
		||||
        => new CashInteraction(_client, ctx.User.Id, BankAction).GetInteraction();
 | 
			
		||||
    private NadekoInteraction CreateCashInteraction()
 | 
			
		||||
        => _inter.Create<object>(ctx.User.Id,
 | 
			
		||||
            new(new(
 | 
			
		||||
                    customId: "cash:bank_show_balance", 
 | 
			
		||||
                    emote: new Emoji("🏦")),
 | 
			
		||||
                BankAction));
 | 
			
		||||
 | 
			
		||||
    [Cmd]
 | 
			
		||||
    [Priority(1)]
 | 
			
		||||
 
 | 
			
		||||
@@ -73,16 +73,6 @@ public partial class Gambling
 | 
			
		||||
 | 
			
		||||
            await ctx.Channel.EmbedAsync(embed);
 | 
			
		||||
        }
 | 
			
		||||
        public sealed class SlotInteraction : NInteraction
 | 
			
		||||
        {
 | 
			
		||||
            public SlotInteraction(DiscordSocketClient client, ulong userId, Func<SocketMessageComponent, Task> action) : base(client, userId, action)
 | 
			
		||||
            {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            protected override NadekoInteractionData Data { get; } = new(Emoji.Parse("🔁"),
 | 
			
		||||
                "slot:again",
 | 
			
		||||
                "Pull Again");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Cmd]
 | 
			
		||||
        public async Task Slot(ShmartNumber amount)
 | 
			
		||||
@@ -117,7 +107,7 @@ public partial class Gambling
 | 
			
		||||
                    .WithImageUrl($"attachment://result.png")
 | 
			
		||||
                    .WithOkColor();
 | 
			
		||||
                
 | 
			
		||||
                // var inter = slotInteraction.GetInteraction();
 | 
			
		||||
                //new(Emoji.Parse("🔁"), "slot:again", "Pull Again");
 | 
			
		||||
                await ctx.Channel.SendFileAsync(imgStream,
 | 
			
		||||
                    "result.png",
 | 
			
		||||
                    embed: eb.Build()
 | 
			
		||||
 
 | 
			
		||||
@@ -424,7 +424,7 @@ public partial class Help : NadekoModule<HelpService>
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Information("No old version list found. Creating a new one.");
 | 
			
		||||
                Log.Information("No old version list found. Creating a new one");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var versionList = JsonSerializer.Deserialize<List<string>>(versionListString);
 | 
			
		||||
@@ -469,7 +469,7 @@ public partial class Help : NadekoModule<HelpService>
 | 
			
		||||
            "https://nadekobot.readthedocs.io/en/latest/"));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private Task SelfhostAction(SocketMessageComponent smc)
 | 
			
		||||
    private Task SelfhostAction(SocketMessageComponent smc, object _)
 | 
			
		||||
        => smc.RespondConfirmAsync(_eb,
 | 
			
		||||
            @"- In case you don't want or cannot Donate to NadekoBot project, but you 
 | 
			
		||||
- NadekoBot is a completely free and fully [open source](https://gitlab.com/kwoth/nadekobot) project which means you can run your own ""selfhosted"" instance on your computer or server for free.
 | 
			
		||||
@@ -484,7 +484,13 @@ public partial class Help : NadekoModule<HelpService>
 | 
			
		||||
    [OnlyPublicBot]
 | 
			
		||||
    public async Task Donate()
 | 
			
		||||
    {
 | 
			
		||||
        var selfhostInter = new DonateSelfhostingInteraction(_client, ctx.User.Id, SelfhostAction);
 | 
			
		||||
        // => new NadekoInteractionData(new Emoji("🖥️"), "donate:selfhosting", "Selfhosting");
 | 
			
		||||
        var selfhostInter = _inter.Create(ctx.User.Id,
 | 
			
		||||
            new SimpleInteraction<object>(new ButtonBuilder(
 | 
			
		||||
                    emote: new Emoji("🖥️"),
 | 
			
		||||
                    customId: "donate:selfhosting",
 | 
			
		||||
                    label: "Selfhosting"),
 | 
			
		||||
                SelfhostAction));
 | 
			
		||||
        
 | 
			
		||||
        var eb = _eb.Create(ctx)
 | 
			
		||||
                    .WithOkColor()
 | 
			
		||||
@@ -525,7 +531,7 @@ Nadeko will DM you the welcome instructions, and you may start using the patron-
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            await (await ctx.User.CreateDMChannelAsync()).EmbedAsync(eb, inter: selfhostInter.GetInteraction());
 | 
			
		||||
            await (await ctx.User.CreateDMChannelAsync()).EmbedAsync(eb, inter: selfhostInter);
 | 
			
		||||
            _ = ctx.OkAsync();
 | 
			
		||||
        }
 | 
			
		||||
        catch
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
namespace NadekoBot.Modules.Help;
 | 
			
		||||
 | 
			
		||||
public class DonateSelfhostingInteraction : NInteraction
 | 
			
		||||
{
 | 
			
		||||
    protected override NadekoInteractionData Data
 | 
			
		||||
        => new NadekoInteractionData(new Emoji("🖥️"), "donate:selfhosting", "Selfhosting");
 | 
			
		||||
    
 | 
			
		||||
    public DonateSelfhostingInteraction(DiscordSocketClient client, ulong userId, Func<SocketMessageComponent, Task> action)
 | 
			
		||||
        : base(client, userId, action)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
namespace NadekoBot.Modules.Help;
 | 
			
		||||
 | 
			
		||||
public class DonateTroubleshootInteraction : NInteraction
 | 
			
		||||
{
 | 
			
		||||
    protected override NadekoInteractionData Data
 | 
			
		||||
        => new NadekoInteractionData(new Emoji("❓"), "donate:troubleshoot", "Troubleshoot");
 | 
			
		||||
    
 | 
			
		||||
    public DonateTroubleshootInteraction(DiscordSocketClient client, ulong userId, Func<SocketMessageComponent, Task> action)
 | 
			
		||||
        : base(client, userId, action)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -433,7 +433,6 @@ public partial class Xp : NadekoModule<XpService>
 | 
			
		||||
                            ? GetText(strs.in_use)
 | 
			
		||||
                            : GetText(strs.use),
 | 
			
		||||
                        "XP_SHOP_USE",
 | 
			
		||||
                        ButtonStyle.Primary,
 | 
			
		||||
                        emote: Emoji.Parse("👐"),
 | 
			
		||||
                        isDisabled: ownedItem.IsUsing);
 | 
			
		||||
 | 
			
		||||
@@ -448,7 +447,6 @@ public partial class Xp : NadekoModule<XpService>
 | 
			
		||||
                {
 | 
			
		||||
                    var button = new ButtonBuilder(GetText(strs.buy),
 | 
			
		||||
                        "XP_SHOP_BUY",
 | 
			
		||||
                        ButtonStyle.Primary,
 | 
			
		||||
                        emote: Emoji.Parse("💰"));
 | 
			
		||||
 | 
			
		||||
                    var inter = new SimpleInteraction<(string key, XpShopItemType type)?>(
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ public static class MessageChannelExtensions
 | 
			
		||||
    public static async Task<IUserMessage> SendAsync(
 | 
			
		||||
        this IMessageChannel channel,
 | 
			
		||||
        string? plainText,
 | 
			
		||||
        NadekoButtonInteraction? inter,
 | 
			
		||||
        NadekoInteraction? inter,
 | 
			
		||||
        Embed? embed = null,
 | 
			
		||||
        IReadOnlyCollection<Embed>? embeds = null,
 | 
			
		||||
        bool sanitizeAll = false)
 | 
			
		||||
@@ -72,7 +72,7 @@ public static class MessageChannelExtensions
 | 
			
		||||
        IEmbedBuilder? embed,
 | 
			
		||||
        string plainText = "",
 | 
			
		||||
        IReadOnlyCollection<IEmbedBuilder>? embeds = null,
 | 
			
		||||
        NadekoButtonInteraction? inter = null)
 | 
			
		||||
        NadekoInteraction? inter = null)
 | 
			
		||||
        => ch.SendAsync(plainText,
 | 
			
		||||
            inter,
 | 
			
		||||
            embed: embed?.Build(),
 | 
			
		||||
@@ -83,7 +83,7 @@ public static class MessageChannelExtensions
 | 
			
		||||
        IEmbedBuilderService eb,
 | 
			
		||||
        string text,
 | 
			
		||||
        MessageType type,
 | 
			
		||||
        NadekoButtonInteraction? inter = null)
 | 
			
		||||
        NadekoInteraction? inter = null)
 | 
			
		||||
    {
 | 
			
		||||
        var builder = eb.Create().WithDescription(text);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,7 @@ public static class SocketMessageComponentExtensions
 | 
			
		||||
        IEmbedBuilder? embed,
 | 
			
		||||
        string plainText = "",
 | 
			
		||||
        IReadOnlyCollection<IEmbedBuilder>? embeds = null,
 | 
			
		||||
        NadekoButtonInteraction? inter = null,
 | 
			
		||||
        NadekoInteraction? inter = null,
 | 
			
		||||
        bool ephemeral = false)
 | 
			
		||||
        => smc.RespondAsync(plainText,
 | 
			
		||||
            embed: embed?.Build(),
 | 
			
		||||
@@ -69,7 +69,7 @@ public static class SocketMessageComponentExtensions
 | 
			
		||||
        string text,
 | 
			
		||||
        MessageType type,
 | 
			
		||||
        bool ephemeral = false,
 | 
			
		||||
        NadekoButtonInteraction? inter = null)
 | 
			
		||||
        NadekoInteraction? inter = null)
 | 
			
		||||
    {
 | 
			
		||||
        var builder = eb.Create().WithDescription(text);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user