INIT
This commit is contained in:
41
TomatenMusicCore/Prompt/Model/ButtonPrompt.cs
Normal file
41
TomatenMusicCore/Prompt/Model/ButtonPrompt.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using DSharpPlus.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using TomatenMusic.Prompt.Option;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
class ButtonPrompt : DiscordPromptBase
|
||||
{
|
||||
public string Content { get; protected set; } = "";
|
||||
public List<DiscordEmbed> Embeds { get; protected set; } = new List<DiscordEmbed>();
|
||||
|
||||
public ButtonPrompt(DiscordPromptBase lastPrompt = null, string content = " ", List<DiscordEmbed> embeds = null) : base(lastPrompt)
|
||||
{
|
||||
this.Content = content;
|
||||
this.Embeds = embeds == null ? new List<DiscordEmbed>() : embeds;
|
||||
}
|
||||
|
||||
protected override Task<DiscordComponent> GetComponentAsync(IPromptOption option)
|
||||
{
|
||||
var myOption = (ButtonPromptOption)option;
|
||||
DiscordComponent component;
|
||||
|
||||
if (myOption.Link != null)
|
||||
component = new DiscordLinkButtonComponent(myOption.Link, myOption.Content, myOption.Disabled, myOption.Emoji);
|
||||
else
|
||||
component = new DiscordButtonComponent(myOption.Style, myOption.CustomID, myOption.Content, myOption.Disabled, myOption.Emoji);
|
||||
return Task.FromResult<DiscordComponent>(component);
|
||||
}
|
||||
|
||||
protected override Task<DiscordMessageBuilder> GetMessageAsync()
|
||||
{
|
||||
return Task.FromResult<DiscordMessageBuilder>(new DiscordMessageBuilder()
|
||||
.WithContent(Content)
|
||||
.AddEmbeds(Embeds));
|
||||
}
|
||||
}
|
||||
}
|
62
TomatenMusicCore/Prompt/Model/CombinedPrompt.cs
Normal file
62
TomatenMusicCore/Prompt/Model/CombinedPrompt.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using DSharpPlus.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using TomatenMusic.Prompt.Option;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TomatenMusic.Util;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
class CombinedPrompt : DiscordPromptBase
|
||||
{
|
||||
public string Content { get; protected set; } = "";
|
||||
public List<DiscordEmbed> Embeds { get; protected set; } = new List<DiscordEmbed>();
|
||||
|
||||
public CombinedPrompt(DiscordPromptBase lastPrompt = null, string content = "Example Content", List<DiscordEmbed> embeds = null) : base(lastPrompt)
|
||||
{
|
||||
this.LastPrompt = lastPrompt;
|
||||
|
||||
this.Content = content;
|
||||
this.Embeds = embeds == null ? new List<DiscordEmbed>() : embeds;
|
||||
}
|
||||
|
||||
protected async override Task<DiscordComponent> GetComponentAsync(IPromptOption option)
|
||||
{
|
||||
if (option is SelectMenuPromptOption)
|
||||
{
|
||||
SelectMenuPromptOption selectOption = (SelectMenuPromptOption)option;
|
||||
List<DiscordSelectComponentOption> options = new List<DiscordSelectComponentOption>();
|
||||
foreach (var item in selectOption.Options)
|
||||
{
|
||||
options.Add(new DiscordSelectComponentOption(item.Label, item.CustomID, item.Description, item.Default, item.Emoji));
|
||||
}
|
||||
|
||||
return new DiscordSelectComponent(selectOption.CustomID, selectOption.Content, options, selectOption.Disabled, selectOption.MinValues, selectOption.MaxValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
var myOption = (ButtonPromptOption)option;
|
||||
DiscordComponent component;
|
||||
|
||||
if (myOption.Link != null)
|
||||
component = new DiscordLinkButtonComponent(myOption.Link, myOption.Content, myOption.Disabled, myOption.Emoji);
|
||||
else
|
||||
component = new DiscordButtonComponent(myOption.Style, myOption.CustomID, myOption.Content, myOption.Disabled, myOption.Emoji);
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected async override Task<DiscordMessageBuilder> GetMessageAsync()
|
||||
{
|
||||
return new DiscordMessageBuilder()
|
||||
.WithContent(Content)
|
||||
.AddEmbeds(Embeds);
|
||||
}
|
||||
}
|
||||
}
|
499
TomatenMusicCore/Prompt/Model/DiscordPromptBase.cs
Normal file
499
TomatenMusicCore/Prompt/Model/DiscordPromptBase.cs
Normal file
@@ -0,0 +1,499 @@
|
||||
using DSharpPlus.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TomatenMusic.Prompt.Option;
|
||||
using TomatenMusic.Util;
|
||||
using DSharpPlus.Exceptions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using DSharpPlus;
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
abstract class DiscordPromptBase
|
||||
{
|
||||
public static List<DiscordPromptBase> ActivePrompts { get; } = new List<DiscordPromptBase>();
|
||||
|
||||
public PromptState State { get; protected set; }
|
||||
public DiscordMessage Message { get; private set; }
|
||||
public DiscordInteraction Interaction { get; private set; }
|
||||
public List<IPromptOption> Options { get; protected set; } = new List<IPromptOption>();
|
||||
public DiscordClient _client { get; set; }
|
||||
public DiscordPromptBase LastPrompt { get; protected set; }
|
||||
public System.Timers.Timer TimeoutTimer { get; set; }
|
||||
|
||||
protected ILogger<DiscordPromptBase> _logger { get; set; }
|
||||
|
||||
protected EventId eventId = new EventId(16, "Prompts");
|
||||
|
||||
protected DiscordPromptBase(DiscordPromptBase lastPrompt)
|
||||
{
|
||||
LastPrompt = lastPrompt;
|
||||
Options = new List<IPromptOption>();
|
||||
IServiceProvider serviceProvider = TomatenMusicBot.ServiceProvider;
|
||||
|
||||
_logger = serviceProvider.GetRequiredService<ILogger<DiscordPromptBase>>();
|
||||
|
||||
|
||||
if (lastPrompt != null)
|
||||
{
|
||||
Options.Add(new ButtonPromptOption
|
||||
{
|
||||
Style = DSharpPlus.ButtonStyle.Danger,
|
||||
Row = 5,
|
||||
Emoji = new DiscordComponentEmoji("↩️"),
|
||||
Run = async (args, sender, option) =>
|
||||
{
|
||||
_ = BackAsync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Options.Add(new ButtonPromptOption
|
||||
{
|
||||
Style = DSharpPlus.ButtonStyle.Danger,
|
||||
Row = 5,
|
||||
Emoji = new DiscordComponentEmoji("❌"),
|
||||
Run = async (args, sender, option) =>
|
||||
{
|
||||
_ = InvalidateAsync();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public async Task InvalidateAsync(bool withEdit = true, bool destroyHistory = false)
|
||||
{
|
||||
foreach (var option in Options)
|
||||
option.UpdateMethod = (prompt) =>
|
||||
{
|
||||
prompt.Disabled = true;
|
||||
return Task.FromResult<IPromptOption>(prompt);
|
||||
};
|
||||
|
||||
if (withEdit)
|
||||
await EditMessageAsync(new DiscordWebhookBuilder().WithContent("This Prompt is invalid!"));
|
||||
ActivePrompts.Remove(this);
|
||||
if (destroyHistory)
|
||||
{
|
||||
if (LastPrompt != null)
|
||||
await LastPrompt.InvalidateAsync(false);
|
||||
await EditMessageAsync(new DiscordWebhookBuilder().WithContent("This Prompt is invalid!"));
|
||||
}
|
||||
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
State = PromptState.INVALID;
|
||||
|
||||
|
||||
_client.ComponentInteractionCreated -= Discord_ComponentInteractionCreated;
|
||||
|
||||
}
|
||||
|
||||
public async Task SendAsync(DiscordChannel channel)
|
||||
{
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
|
||||
IServiceProvider serviceProvider = TomatenMusicBot.ServiceProvider;
|
||||
var client = serviceProvider.GetRequiredService<DiscordShardedClient>();
|
||||
_client = client.GetShard( (ulong) channel.GuildId);
|
||||
|
||||
_client.ComponentInteractionCreated += Discord_ComponentInteractionCreated;
|
||||
ActivePrompts.Add(this);
|
||||
AddGuids();
|
||||
DiscordMessageBuilder builder = await GetMessageAsync();
|
||||
builder = await AddComponentsAsync(builder);
|
||||
|
||||
|
||||
Message = await builder.SendAsync(channel);
|
||||
State = PromptState.OPEN;
|
||||
}
|
||||
|
||||
public async Task SendAsync(DiscordInteraction interaction, bool ephemeral = false)
|
||||
{
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
|
||||
IServiceProvider serviceProvider = TomatenMusicBot.ServiceProvider;
|
||||
var client = serviceProvider.GetRequiredService<DiscordShardedClient>();
|
||||
_client = client.GetShard((ulong)interaction.GuildId);
|
||||
|
||||
_client.ComponentInteractionCreated += Discord_ComponentInteractionCreated;
|
||||
ActivePrompts.Add(this);
|
||||
|
||||
AddGuids();
|
||||
DiscordFollowupMessageBuilder builder = await GetFollowupMessageAsync();
|
||||
builder = await AddComponentsAsync(builder);
|
||||
builder.AsEphemeral(ephemeral);
|
||||
|
||||
Interaction = interaction;
|
||||
Message = await interaction.CreateFollowupMessageAsync(builder);
|
||||
State = PromptState.OPEN;
|
||||
|
||||
long timeoutTime = (Interaction.CreationTimestamp.ToUnixTimeMilliseconds() + 900000) - DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
if (TimeoutTimer != null)
|
||||
TimeoutTimer.Close();
|
||||
|
||||
TimeoutTimer = new System.Timers.Timer(timeoutTime);
|
||||
TimeoutTimer.Elapsed += OnTimeout;
|
||||
TimeoutTimer.AutoReset = false;
|
||||
TimeoutTimer.Start();
|
||||
}
|
||||
|
||||
public async Task UseAsync(DiscordMessage message)
|
||||
{
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
|
||||
IServiceProvider serviceProvider = TomatenMusicBot.ServiceProvider;
|
||||
var client = serviceProvider.GetRequiredService<DiscordShardedClient>();
|
||||
_client = client.GetShard((ulong)message.Channel.GuildId);
|
||||
|
||||
_client.ComponentInteractionCreated += Discord_ComponentInteractionCreated;
|
||||
ActivePrompts.Add(this);
|
||||
|
||||
AddGuids();
|
||||
DiscordWebhookBuilder builder = await GetWebhookMessageAsync();
|
||||
|
||||
await EditMessageAsync(builder);
|
||||
State = PromptState.OPEN;
|
||||
|
||||
}
|
||||
|
||||
public async Task UseAsync(DiscordInteraction interaction, DiscordMessage message)
|
||||
{
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
|
||||
IServiceProvider serviceProvider = TomatenMusicBot.ServiceProvider;
|
||||
var client = serviceProvider.GetRequiredService<DiscordShardedClient>();
|
||||
_client = client.GetShard((ulong)interaction.GuildId);
|
||||
|
||||
_client.ComponentInteractionCreated += Discord_ComponentInteractionCreated;
|
||||
|
||||
ActivePrompts.Add(this);
|
||||
AddGuids();
|
||||
DiscordWebhookBuilder builder = await GetWebhookMessageAsync();
|
||||
Interaction = interaction;
|
||||
Message = message;
|
||||
await EditMessageAsync(builder);
|
||||
State = PromptState.OPEN;
|
||||
|
||||
long timeoutTime = (Interaction.CreationTimestamp.ToUnixTimeMilliseconds() + 900000) - DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
if (TimeoutTimer != null)
|
||||
TimeoutTimer.Close();
|
||||
|
||||
TimeoutTimer = new System.Timers.Timer(timeoutTime);
|
||||
TimeoutTimer.Elapsed += OnTimeout;
|
||||
TimeoutTimer.AutoReset = false;
|
||||
TimeoutTimer.Start();
|
||||
|
||||
}
|
||||
|
||||
private void OnTimeout(object? sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
_ = InvalidateAsync();
|
||||
}
|
||||
|
||||
private void AddGuids()
|
||||
{
|
||||
foreach (var item in Options)
|
||||
{
|
||||
item.CustomID = RandomUtil.GenerateGuid();
|
||||
if (item is SelectMenuPromptOption)
|
||||
{
|
||||
SelectMenuPromptOption menuItem = (SelectMenuPromptOption)item;
|
||||
foreach (var option in menuItem.Options)
|
||||
{
|
||||
option.CustomID = RandomUtil.GenerateGuid();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//this.Options = options;
|
||||
}
|
||||
|
||||
protected abstract Task<DiscordComponent> GetComponentAsync(IPromptOption option);
|
||||
|
||||
protected abstract Task<DiscordMessageBuilder> GetMessageAsync();
|
||||
|
||||
private async Task<DiscordFollowupMessageBuilder> GetFollowupMessageAsync()
|
||||
{
|
||||
DiscordMessageBuilder oldBuilder = await GetMessageAsync();
|
||||
|
||||
return new DiscordFollowupMessageBuilder()
|
||||
.WithContent(oldBuilder.Content)
|
||||
.AddEmbeds(oldBuilder.Embeds);
|
||||
|
||||
}
|
||||
private async Task<DiscordWebhookBuilder> GetWebhookMessageAsync()
|
||||
{
|
||||
DiscordMessageBuilder oldBuilder = await GetMessageAsync();
|
||||
|
||||
return new DiscordWebhookBuilder()
|
||||
.WithContent(oldBuilder.Content)
|
||||
.AddEmbeds(oldBuilder.Embeds);
|
||||
|
||||
}
|
||||
|
||||
public async Task UpdateAsync()
|
||||
{
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
await EditMessageAsync(await GetWebhookMessageAsync());
|
||||
|
||||
}
|
||||
|
||||
private async Task UpdateOptionsAsync()
|
||||
{
|
||||
List<IPromptOption> options = new List<IPromptOption>();
|
||||
foreach (var option in this.Options)
|
||||
options.Add(await option.UpdateMethod.Invoke(option));
|
||||
this.Options = options;
|
||||
}
|
||||
|
||||
protected async Task Discord_ComponentInteractionCreated(DSharpPlus.DiscordClient sender, DSharpPlus.EventArgs.ComponentInteractionCreateEventArgs e)
|
||||
{
|
||||
if (State == PromptState.INVALID)
|
||||
return;
|
||||
|
||||
foreach (var option in Options)
|
||||
{
|
||||
if (option.CustomID == e.Id)
|
||||
{
|
||||
|
||||
await e.Interaction.CreateResponseAsync(DSharpPlus.InteractionResponseType.DeferredMessageUpdate);
|
||||
_ = option.Run.Invoke(e, sender, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task EditMessageAsync(DiscordWebhookBuilder builder)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Interaction != null)
|
||||
{
|
||||
await AddComponentsAsync(builder);
|
||||
try
|
||||
{
|
||||
Message = await Interaction.EditFollowupMessageAsync(Message.Id, builder);
|
||||
}catch (Exception e)
|
||||
{
|
||||
Message = await Interaction.EditOriginalResponseAsync(builder);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
DiscordMessageBuilder msgbuilder = new DiscordMessageBuilder()
|
||||
.AddEmbeds(builder.Embeds)
|
||||
.WithContent(builder.Content);
|
||||
await AddComponentsAsync(msgbuilder);
|
||||
Message = await Message.ModifyAsync(msgbuilder);
|
||||
}
|
||||
}catch (BadRequestException e)
|
||||
{
|
||||
_logger.LogError(e.Errors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected async Task<DiscordMessageBuilder> AddComponentsAsync(DiscordMessageBuilder builder)
|
||||
{
|
||||
await UpdateOptionsAsync();
|
||||
builder.ClearComponents();
|
||||
|
||||
List<DiscordComponent> row1 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row2 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row3 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row4 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row5 = new List<DiscordComponent>(5);
|
||||
|
||||
foreach (var option in Options)
|
||||
{
|
||||
switch (option.Row)
|
||||
{
|
||||
case 1:
|
||||
row1.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 2:
|
||||
row2.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 3:
|
||||
row3.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 4:
|
||||
row4.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 5:
|
||||
row5.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalid Row! Must be between 1 and 5", "Row");
|
||||
}
|
||||
}
|
||||
if (row1.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row1);
|
||||
}
|
||||
if (row2.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row2);
|
||||
}
|
||||
if (row3.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row3);
|
||||
}
|
||||
if (row4.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row4);
|
||||
}
|
||||
if (row5.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row5);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected async Task<DiscordFollowupMessageBuilder> AddComponentsAsync(DiscordFollowupMessageBuilder builder)
|
||||
{
|
||||
await UpdateOptionsAsync();
|
||||
builder.ClearComponents();
|
||||
|
||||
List<DiscordComponent> row1 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row2 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row3 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row4 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row5 = new List<DiscordComponent>(5);
|
||||
|
||||
foreach (var option in Options)
|
||||
{
|
||||
switch (option.Row)
|
||||
{
|
||||
case 1:
|
||||
row1.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 2:
|
||||
row2.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 3:
|
||||
row3.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 4:
|
||||
row4.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 5:
|
||||
row5.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalid Row! Must be between 1 and 5", "Row");
|
||||
}
|
||||
}
|
||||
if (row1.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row1);
|
||||
}
|
||||
if (row2.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row2);
|
||||
}
|
||||
if (row3.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row3);
|
||||
}
|
||||
if (row4.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row4);
|
||||
}
|
||||
if (row5.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row5);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected async Task<DiscordWebhookBuilder> AddComponentsAsync(DiscordWebhookBuilder builder)
|
||||
{
|
||||
await UpdateOptionsAsync();
|
||||
builder.ClearComponents();
|
||||
|
||||
List<DiscordComponent> row1 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row2 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row3 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row4 = new List<DiscordComponent>(5);
|
||||
List<DiscordComponent> row5 = new List<DiscordComponent>(5);
|
||||
|
||||
foreach (var option in Options)
|
||||
{
|
||||
switch (option.Row)
|
||||
{
|
||||
case 1:
|
||||
row1.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 2:
|
||||
row2.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 3:
|
||||
row3.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 4:
|
||||
row4.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
case 5:
|
||||
row5.Add(await GetComponentAsync(option));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalid Row! Must be between 1 and 5", "Row");
|
||||
}
|
||||
}
|
||||
if (row1.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row1);
|
||||
}
|
||||
if (row2.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row2);
|
||||
}
|
||||
if (row3.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row3);
|
||||
}
|
||||
if (row4.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row4);
|
||||
}
|
||||
if (row5.Count != 0)
|
||||
{
|
||||
builder.AddComponents(row5);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public async Task BackAsync()
|
||||
{
|
||||
|
||||
if (LastPrompt == null)
|
||||
return;
|
||||
_client.ComponentInteractionCreated -= LastPrompt.Discord_ComponentInteractionCreated;
|
||||
|
||||
await InvalidateAsync(false);
|
||||
if (Interaction == null)
|
||||
await LastPrompt.UseAsync(Message);
|
||||
else
|
||||
await LastPrompt.UseAsync(Interaction, Message);
|
||||
}
|
||||
|
||||
public void AddOption(IPromptOption option)
|
||||
{
|
||||
Options.Add(option);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
138
TomatenMusicCore/Prompt/Model/PaginatedButtonPrompt.cs
Normal file
138
TomatenMusicCore/Prompt/Model/PaginatedButtonPrompt.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using DSharpPlus.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TomatenMusic.Util;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.EventArgs;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TomatenMusic.Prompt.Option;
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
abstract class PaginatedButtonPrompt<T> : ButtonPrompt
|
||||
{
|
||||
protected PageManager<T> PageManager { get; set; }
|
||||
protected int CurrentPage { get; set; } = 1;
|
||||
public string Title { get; set; }
|
||||
|
||||
public PaginatedButtonPrompt(string title, List<T> items, DiscordPromptBase lastPrompt = null) : base(lastPrompt)
|
||||
{
|
||||
PageManager = new PageManager<T>(items, 9);
|
||||
Title = title;
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
int currentNumber = i + 1;
|
||||
|
||||
ButtonPromptOption option = new ButtonPromptOption()
|
||||
{
|
||||
Style = DSharpPlus.ButtonStyle.Primary,
|
||||
Row = i < 5 ? 1 : 2,
|
||||
UpdateMethod = async (option) =>
|
||||
{
|
||||
option.Disabled = PageManager.GetPage(CurrentPage).Count < currentNumber;
|
||||
return option;
|
||||
},
|
||||
Run = async (args, sender, prompt) =>
|
||||
{
|
||||
List<T> items = PageManager.GetPage(CurrentPage);
|
||||
await OnSelect(items[currentNumber-1], args, sender);
|
||||
}
|
||||
};
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
option.Emoji = new DiscordComponentEmoji("1️⃣");
|
||||
break;
|
||||
case 1:
|
||||
option.Emoji = new DiscordComponentEmoji("2️⃣");
|
||||
break;
|
||||
case 2:
|
||||
option.Emoji = new DiscordComponentEmoji("3️⃣");
|
||||
break;
|
||||
case 3:
|
||||
option.Emoji = new DiscordComponentEmoji("4️⃣");
|
||||
break;
|
||||
case 4:
|
||||
option.Emoji = new DiscordComponentEmoji("5️⃣");
|
||||
break;
|
||||
case 5:
|
||||
option.Emoji = new DiscordComponentEmoji("6️⃣");
|
||||
break;
|
||||
case 6:
|
||||
option.Emoji = new DiscordComponentEmoji("7️⃣");
|
||||
break;
|
||||
case 7:
|
||||
option.Emoji = new DiscordComponentEmoji("8️⃣");
|
||||
break;
|
||||
case 8:
|
||||
option.Emoji = new DiscordComponentEmoji("9️⃣");
|
||||
break;
|
||||
}
|
||||
|
||||
AddOption(option);
|
||||
}
|
||||
|
||||
AddOption(new ButtonPromptOption
|
||||
{
|
||||
Style = ButtonStyle.Secondary,
|
||||
Emoji= new DiscordComponentEmoji("⬅️"),
|
||||
Row = 3,
|
||||
UpdateMethod = async (prompt) =>
|
||||
{
|
||||
prompt.Disabled = CurrentPage - 1 == 0;
|
||||
return prompt;
|
||||
},
|
||||
Run = async (args, sender, prompt) =>
|
||||
{
|
||||
CurrentPage--;
|
||||
await UpdateAsync();
|
||||
|
||||
}
|
||||
});
|
||||
AddOption(new ButtonPromptOption
|
||||
{
|
||||
Style = ButtonStyle.Secondary,
|
||||
Emoji = new DiscordComponentEmoji("➡️"),
|
||||
Row = 3,
|
||||
UpdateMethod = async (prompt) =>
|
||||
{
|
||||
prompt.Disabled = PageManager.GetTotalPages() == CurrentPage;
|
||||
return prompt;
|
||||
},
|
||||
Run = async (args, sender, prompt) =>
|
||||
{
|
||||
CurrentPage++;
|
||||
await UpdateAsync();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public abstract Task OnSelect(T item, ComponentInteractionCreateEventArgs args, DiscordClient sender);
|
||||
|
||||
protected int GetTotalPages()
|
||||
{
|
||||
return PageManager.GetTotalPages();
|
||||
}
|
||||
|
||||
protected async override Task<DiscordMessageBuilder> GetMessageAsync()
|
||||
{
|
||||
DiscordEmbedBuilder builder = new DiscordEmbedBuilder()
|
||||
.WithTitle(Title)
|
||||
.WithFooter($"Page {CurrentPage} of {GetTotalPages()}")
|
||||
.WithDescription("Select your desired Tracks");
|
||||
|
||||
return PopulateMessage(builder);
|
||||
|
||||
}
|
||||
|
||||
protected abstract DiscordMessageBuilder PopulateMessage(DiscordEmbedBuilder builder);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
160
TomatenMusicCore/Prompt/Model/PaginatedSelectPrompt.cs
Normal file
160
TomatenMusicCore/Prompt/Model/PaginatedSelectPrompt.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using DSharpPlus.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TomatenMusic.Util;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.EventArgs;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TomatenMusic.Prompt.Option;
|
||||
using System.Linq;
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
abstract class PaginatedSelectPrompt<T> : CombinedPrompt
|
||||
{
|
||||
protected PageManager<T> PageManager { get; set; }
|
||||
protected int CurrentPage { get; set; } = 1;
|
||||
|
||||
public string Title { get; set; }
|
||||
public List<T> SelectedItems { get; set; } = new List<T>();
|
||||
|
||||
|
||||
public PaginatedSelectPrompt(string title, List<T> items, DiscordPromptBase lastPrompt = null, List<DiscordEmbed> embeds = null) : base(lastPrompt)
|
||||
{
|
||||
Embeds = embeds;
|
||||
PageManager = new PageManager<T>(items, 10);
|
||||
Title = title;
|
||||
AddOption(new SelectMenuPromptOption
|
||||
{
|
||||
Row = 1,
|
||||
MinValues = 1,
|
||||
MaxValues = PageManager.GetPage(CurrentPage).Count,
|
||||
Content = "Select a Value",
|
||||
UpdateMethod = async (option) =>
|
||||
{
|
||||
SelectMenuPromptOption _option = (SelectMenuPromptOption)option;
|
||||
|
||||
_option.MaxValues = PageManager.GetPage(CurrentPage).Count;
|
||||
_option.Options.Clear();
|
||||
foreach (var item in PageManager.GetPage(CurrentPage))
|
||||
{
|
||||
_option.Options.Add(await GetOption(item));
|
||||
}
|
||||
foreach (var item in _option.Options)
|
||||
{
|
||||
foreach (var sOption in SelectedItems)
|
||||
{
|
||||
PaginatedSelectMenuOption<T> _item = (PaginatedSelectMenuOption<T>)item;
|
||||
if (_item.Item.Equals(sOption))
|
||||
{
|
||||
_option.CurrentValues.Add(_item.CustomID);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return _option;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
AddOption(new ButtonPromptOption
|
||||
{
|
||||
Style = ButtonStyle.Secondary,
|
||||
Emoji = new DiscordComponentEmoji("⬅️"),
|
||||
Row = 2,
|
||||
UpdateMethod = async (prompt) =>
|
||||
{
|
||||
prompt.Disabled = CurrentPage - 1 == 0;
|
||||
return prompt;
|
||||
},
|
||||
Run = async (args, sender, prompt) =>
|
||||
{
|
||||
CurrentPage--;
|
||||
await UpdateAsync();
|
||||
|
||||
}
|
||||
});
|
||||
AddOption(new ButtonPromptOption
|
||||
{
|
||||
Style = ButtonStyle.Secondary,
|
||||
Emoji = new DiscordComponentEmoji("➡️"),
|
||||
Row = 2,
|
||||
UpdateMethod = async (prompt) =>
|
||||
{
|
||||
prompt.Disabled = PageManager.GetTotalPages() == CurrentPage;
|
||||
return prompt;
|
||||
},
|
||||
Run = async (args, sender, prompt) =>
|
||||
{
|
||||
CurrentPage++;
|
||||
await UpdateAsync();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private async Task<PaginatedSelectMenuOption<T>> GetOption(T item)
|
||||
{
|
||||
var option = await ConvertToOption(item);
|
||||
option.Item = item;
|
||||
option.CustomID = RandomUtil.GenerateGuid();
|
||||
option.Default = SelectedItems.Contains(item);
|
||||
option.OnSelected = async (args, sender, option) =>
|
||||
{
|
||||
PaginatedSelectMenuOption<T> _option = (PaginatedSelectMenuOption<T>)option;
|
||||
if (!SelectedItems.Contains(_option.Item))
|
||||
SelectedItems.Add(_option.Item);
|
||||
await OnSelect(_option.Item, args, sender);
|
||||
|
||||
};
|
||||
option.OnUnselected = async (args, sender, option) =>
|
||||
{
|
||||
PaginatedSelectMenuOption<T> _option = (PaginatedSelectMenuOption<T>)option;
|
||||
SelectedItems.Remove(_option.Item);
|
||||
await OnUnselect(_option.Item, args, sender);
|
||||
};
|
||||
|
||||
|
||||
return option;
|
||||
}
|
||||
public abstract Task<PaginatedSelectMenuOption<T>> ConvertToOption(T item);
|
||||
|
||||
public abstract Task OnSelect(T item, ComponentInteractionCreateEventArgs args, DiscordClient sender);
|
||||
|
||||
public abstract Task OnUnselect(T item, ComponentInteractionCreateEventArgs args, DiscordClient sender);
|
||||
|
||||
protected int GetTotalPages()
|
||||
{
|
||||
return PageManager.GetTotalPages();
|
||||
}
|
||||
|
||||
protected async override Task<DiscordMessageBuilder> GetMessageAsync()
|
||||
{
|
||||
DiscordEmbedBuilder builder;
|
||||
if (Embeds != null)
|
||||
{
|
||||
builder = new DiscordEmbedBuilder(Embeds[0]);
|
||||
}else
|
||||
{
|
||||
builder = new DiscordEmbedBuilder();
|
||||
}
|
||||
|
||||
builder
|
||||
.WithTitle(Title)
|
||||
.WithFooter($"Page {CurrentPage} of {GetTotalPages()}");
|
||||
|
||||
return PopulateMessage(builder);
|
||||
|
||||
}
|
||||
|
||||
protected abstract DiscordMessageBuilder PopulateMessage(DiscordEmbedBuilder builder);
|
||||
|
||||
public class PaginatedSelectMenuOption<I> : SelectMenuOption
|
||||
{
|
||||
public I Item { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
15
TomatenMusicCore/Prompt/Model/PromptState.cs
Normal file
15
TomatenMusicCore/Prompt/Model/PromptState.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
enum PromptState
|
||||
{
|
||||
|
||||
PREPARED,
|
||||
OPEN,
|
||||
INVALID,
|
||||
RESPONDED
|
||||
}
|
||||
}
|
48
TomatenMusicCore/Prompt/Model/SelectPrompt.cs
Normal file
48
TomatenMusicCore/Prompt/Model/SelectPrompt.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using DSharpPlus.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TomatenMusic.Prompt.Option;
|
||||
using System.Linq;
|
||||
using DSharpPlus;
|
||||
using DSharpPlus.EventArgs;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TomatenMusic.Util;
|
||||
|
||||
|
||||
namespace TomatenMusic.Prompt.Model
|
||||
{
|
||||
class SelectPrompt : DiscordPromptBase
|
||||
{
|
||||
public List<DiscordEmbed> Embeds { get; protected set; } = new List<DiscordEmbed>();
|
||||
public string Content { get; protected set; } = "";
|
||||
public SelectPrompt(DiscordPromptBase lastPrompt = null, string content = " Example", List<DiscordEmbed> embeds = null) : base(lastPrompt)
|
||||
{
|
||||
|
||||
this.Content = content;
|
||||
this.Embeds = embeds == null ? new List<DiscordEmbed>() : embeds;
|
||||
}
|
||||
|
||||
protected async override Task<DiscordComponent> GetComponentAsync(IPromptOption option)
|
||||
{
|
||||
|
||||
SelectMenuPromptOption selectOption = (SelectMenuPromptOption)option;
|
||||
List<DiscordSelectComponentOption> options = new List<DiscordSelectComponentOption>();
|
||||
foreach ( var item in selectOption.Options)
|
||||
{
|
||||
options.Add(new DiscordSelectComponentOption(item.Label, item.CustomID, item.Description, item.Default, item.Emoji));
|
||||
}
|
||||
|
||||
return new DiscordSelectComponent(selectOption.CustomID, selectOption.Content, options, selectOption.Disabled, selectOption.MinValues, selectOption.MaxValues);
|
||||
}
|
||||
|
||||
protected async override Task<DiscordMessageBuilder> GetMessageAsync()
|
||||
{
|
||||
return new DiscordMessageBuilder()
|
||||
.WithContent(Content)
|
||||
.AddEmbeds(Embeds);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user