This commit is contained in:
Tim Müller
2022-03-28 19:52:42 +02:00
commit d432575da6
75 changed files with 6390 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.EventArgs;
using Lavalink4NET.Player;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TomatenMusic.Music.Entitites;
using TomatenMusic.Prompt;
using TomatenMusic.Prompt.Model;
using TomatenMusic.Util;
using TomatenMusicCore.Music;
namespace TomatenMusicCore.Prompt.Implementation
{
class PlaylistSongSelectorPrompt : PaginatedSelectPrompt<TomatenMusicTrack>
{
public bool IsConfirmed { get; set; }
public Func<TrackList, Task> ConfirmCallback { get; set; } = (tracks) =>
{
return Task.CompletedTask;
};
public ILavalinkPlaylist Playlist { get; private set; }
public PlaylistSongSelectorPrompt(ILavalinkPlaylist playlist, DiscordPromptBase lastPrompt = null, List<DiscordEmbed> embeds = null) : base(playlist.Title, playlist.Tracks.ToList(), lastPrompt, embeds)
{
Playlist = playlist;
AddOption(new ButtonPromptOption
{
Emoji = new DiscordComponentEmoji("✔️"),
Row = 3,
Style = ButtonStyle.Success,
Run = async (args, client, option) =>
{
if (SelectedItems.Count == 0)
{
await args.Interaction.CreateFollowupMessageAsync(new DiscordFollowupMessageBuilder().WithContent("Please Select a Song!").AsEphemeral(true));
return;
}
IsConfirmed = true;
_ = ConfirmCallback.Invoke(new TrackList(SelectedItems));
}
});
}
public override Task<PaginatedSelectMenuOption<TomatenMusicTrack>> ConvertToOption(TomatenMusicTrack item)
{
return Task.FromResult<PaginatedSelectMenuOption<TomatenMusicTrack>>(new PaginatedSelectMenuOption<TomatenMusicTrack>
{
Label = item.Title,
Description = item.Author
});
}
public override Task OnSelect(TomatenMusicTrack item, ComponentInteractionCreateEventArgs args, DiscordClient sender)
{
_logger.LogDebug($"Added {item.Title}, {SelectedItems}");
return Task.CompletedTask;
}
public override Task OnUnselect(TomatenMusicTrack item, ComponentInteractionCreateEventArgs args, DiscordClient sender)
{
_logger.LogDebug($"Removed {item.Title}");
return Task.CompletedTask;
}
public async Task<TrackList> AwaitSelectionAsync()
{
return await Task.Run(() =>
{
while (!IsConfirmed)
{
if (State == PromptState.INVALID)
throw new InvalidOperationException("Prompt has been Invalidated");
}
IsConfirmed = false;
return new TrackList(SelectedItems);
});
}
protected override DiscordMessageBuilder PopulateMessage(DiscordEmbedBuilder builder)
{
builder.WithTitle(Title);
builder.WithDescription(Common.TrackListString(PageManager.GetPage(CurrentPage), 4000));
builder.WithUrl(Playlist.Url);
builder.WithAuthor(Playlist.AuthorName, Playlist.AuthorUri.ToString(), Playlist.AuthorThumbnail.ToString());
List<DiscordEmbed> embeds = new List<DiscordEmbed>();
embeds.Add(builder.Build());
if (Embeds != null)
embeds.AddRange(Embeds);
return new DiscordMessageBuilder().AddEmbeds(embeds);
}
}
}

View File

@@ -0,0 +1,278 @@
using DSharpPlus.Entities;
using Lavalink4NET.Player;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using TomatenMusic.Music;
using TomatenMusic.Prompt.Model;
using TomatenMusic.Prompt.Option;
using TomatenMusic.Util;
namespace TomatenMusic.Prompt.Implementation
{
class QueuePrompt : ButtonPrompt
{
public static void InvalidateFor(ulong guildId)
{
foreach (var prompt in ActivePrompts)
{
if (prompt.State != PromptState.OPEN)
continue;
if (!(prompt is QueuePrompt))
continue;
if (((QueuePrompt)prompt).Player.GuildId != guildId)
continue;
_ = prompt.InvalidateAsync();
}
}
public static void UpdateFor(ulong guildId)
{
_ = Task.Delay(400).ContinueWith(async (task) =>
{
foreach (var prompt in ActivePrompts)
{
if (prompt.State != PromptState.OPEN)
continue;
if (!(prompt is QueuePrompt))
continue;
if (((QueuePrompt)prompt).Player.GuildId != guildId)
continue;
_ = prompt.UpdateAsync();
}
});
}
public GuildPlayer Player { get; private set; }
public QueuePrompt(GuildPlayer player, DiscordPromptBase lastPrompt = null, List<DiscordEmbed> embeds = null) : base(lastPrompt, embeds: embeds)
{
Player = player;
AddOption(
new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("⏯️"),
Row = 1,
UpdateMethod = (option) =>
{
ButtonPromptOption button = (ButtonPromptOption)option;
if (player.State == PlayerState.Paused)
button.Style = DSharpPlus.ButtonStyle.Danger;
else
button.Style = DSharpPlus.ButtonStyle.Success;
return Task.FromResult((IPromptOption) button);
},
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
await Player.TogglePauseAsync();
}
}
);
AddOption(new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("⏮️"),
Row = 1,
Style = DSharpPlus.ButtonStyle.Secondary,
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
try
{
await Player.RewindAsync();
}catch (Exception ex)
{
}
}
}
);
AddOption(new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("⏹️"),
Row = 1,
Style = DSharpPlus.ButtonStyle.Secondary,
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
await Player.DisconnectAsync();
}
});
AddOption(new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("⏭️"),
Row = 1,
Style = DSharpPlus.ButtonStyle.Secondary,
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
await Player.SkipAsync();
System.Timers.Timer timer = new System.Timers.Timer(800);
timer.Elapsed += (s, args) =>
{
_ = UpdateAsync();
timer.Stop();
};
timer.Start();
}
}
);
AddOption(
new ButtonPromptOption()
{
Row = 1,
UpdateMethod = (option) =>
{
ButtonPromptOption button = (ButtonPromptOption)option;
if (player.PlayerQueue.LoopType == LoopType.TRACK)
{
button.Style = DSharpPlus.ButtonStyle.Success;
button.Emoji = new DiscordComponentEmoji("🔂");
}
else if (player.PlayerQueue.LoopType == LoopType.QUEUE)
{
button.Style = DSharpPlus.ButtonStyle.Success;
button.Emoji = new DiscordComponentEmoji("🔁");
}
else
{
button.Style = DSharpPlus.ButtonStyle.Danger;
button.Emoji = null;
button.Content = "Loop";
}
return Task.FromResult((IPromptOption)button);
},
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
switch (player.PlayerQueue.LoopType)
{
case LoopType.NONE:
_ = Player.SetLoopAsync(LoopType.QUEUE);
break;
case LoopType.QUEUE:
_ = Player.SetLoopAsync(LoopType.TRACK);
break;
case LoopType.TRACK:
_ = Player.SetLoopAsync(LoopType.NONE);
break;
}
}
}
);
AddOption(new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("🔀"),
Row = 2,
Style = DSharpPlus.ButtonStyle.Secondary,
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
await Player.ShuffleAsync();
}
});
AddOption(new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("🚫"),
Row = 2,
Style = DSharpPlus.ButtonStyle.Secondary,
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
Player.PlayerQueue.Queue.Clear();
_ = UpdateAsync();
}
});
AddOption(
new ButtonPromptOption()
{
Emoji = new DiscordComponentEmoji("➡️"),
Content = "AutoPlay",
Row = 2,
UpdateMethod = (option) =>
{
ButtonPromptOption button = (ButtonPromptOption)option;
if (player.Autoplay)
button.Style = DSharpPlus.ButtonStyle.Success;
else
button.Style = DSharpPlus.ButtonStyle.Danger;
return Task.FromResult((IPromptOption)button);
},
Run = async (args, sender, option) =>
{
if (!await Player.AreActionsAllowedAsync((DiscordMember)args.User))
{
_ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction"));
return;
}
Player.Autoplay = !Player.Autoplay;
_ = UpdateAsync();
}
}
);
}
protected async override Task<DiscordMessageBuilder> GetMessageAsync()
{
return new DiscordMessageBuilder()
.AddEmbed(Common.GetQueueEmbed(Player))
.AddEmbed(await Common.CurrentSongEmbedAsync(Player))
.AddEmbeds(Embeds);
}
}
}

View File

@@ -0,0 +1,31 @@
using DSharpPlus.Entities;
using Lavalink4NET.Player;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using TomatenMusic.Music.Entitites;
using TomatenMusic.Prompt.Buttons;
using TomatenMusic.Prompt.Model;
using TomatenMusic.Util;
using TomatenMusicCore.Music;
namespace TomatenMusic.Prompt.Implementation
{
class SongActionPrompt : ButtonPrompt
{
public LavalinkTrack Track { get; set; }
public SongActionPrompt(TomatenMusicTrack track, DiscordMember requestMember, List<DiscordEmbed> embeds = null)
{
Embeds = embeds == null ? new List<DiscordEmbed>() : embeds;
Track = track;
AddOption(new AddToQueueButton(new TrackList() { track }, 1, requestMember));
}
protected async override Task<DiscordMessageBuilder> GetMessageAsync()
{
return new DiscordMessageBuilder().AddEmbed(Common.AsEmbed(Track)).AddEmbeds(Embeds);
}
}
}

View File

@@ -0,0 +1,41 @@
using DSharpPlus.Entities;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using TomatenMusic.Music.Entitites;
using TomatenMusic.Prompt.Model;
using System.Linq;
using TomatenMusic.Util;
using TomatenMusic.Music;
using Microsoft.Extensions.Logging;
using TomatenMusic.Prompt.Buttons;
using Lavalink4NET.Player;
using TomatenMusicCore.Music;
namespace TomatenMusic.Prompt.Implementation
{
class SongListActionPrompt : ButtonPrompt
{
//TODO
public TrackList Tracks { get; private set; }
public SongListActionPrompt(TrackList tracks, DiscordMember requestMember, DiscordPromptBase lastPrompt = null) : base(lastPrompt)
{
Tracks = tracks;
AddOption(new AddToQueueButton(tracks, 1, requestMember));
}
protected override Task<DiscordMessageBuilder> GetMessageAsync()
{
DiscordEmbedBuilder builder = new DiscordEmbedBuilder()
.WithTitle("What do you want to do with these Tracks?");
builder.WithDescription(Common.TrackListString(Tracks, 1000));
return Task.FromResult(new DiscordMessageBuilder().WithEmbed(builder.Build()));
}
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Text;
using TomatenMusic.Prompt.Model;
using DSharpPlus;
using System.Threading.Tasks;
using DSharpPlus.EventArgs;
using Microsoft.Extensions.Logging;
using DSharpPlus.Entities;
using TomatenMusic.Util;
using TomatenMusic.Music.Entitites;
using TomatenMusic.Music;
using System.Linq;
using Lavalink4NET.Player;
using TomatenMusicCore.Music;
namespace TomatenMusic.Prompt.Implementation
{
sealed class SongSelectorPrompt : PaginatedSelectPrompt<LavalinkTrack>
{
public bool IsConfirmed { get; set; }
public Func<TrackList, Task> ConfirmCallback { get; set; } = (tracks) =>
{
return Task.CompletedTask;
};
public IEnumerable<LavalinkTrack> Tracks { get; private set; }
public SongSelectorPrompt(string title, IEnumerable<LavalinkTrack> tracks, DiscordPromptBase lastPrompt = null, List<DiscordEmbed> embeds = null) : base(title, tracks.ToList(), lastPrompt, embeds)
{
Title = title;
Tracks = tracks;
AddOption(new ButtonPromptOption
{
Emoji = new DiscordComponentEmoji("✔️"),
Row = 3,
Style = ButtonStyle.Success,
Run = async (args, client, option) =>
{
if (SelectedItems.Count == 0)
{
await args.Interaction.CreateFollowupMessageAsync(new DiscordFollowupMessageBuilder().WithContent("Please Select a Song!").AsEphemeral(true));
return;
}
IsConfirmed = true;
_ = ConfirmCallback.Invoke(new TrackList(SelectedItems));
}
});
}
public override Task<PaginatedSelectMenuOption<LavalinkTrack>> ConvertToOption(LavalinkTrack item)
{
return Task.FromResult<PaginatedSelectMenuOption<LavalinkTrack>>(new PaginatedSelectMenuOption<LavalinkTrack>
{
Label = item.Title,
Description = item.Author
});
}
public override Task OnSelect(LavalinkTrack item, ComponentInteractionCreateEventArgs args, DiscordClient sender)
{
_logger.LogDebug($"Added {item.Title}, {SelectedItems}");
return Task.CompletedTask;
}
public override Task OnUnselect(LavalinkTrack item, ComponentInteractionCreateEventArgs args, DiscordClient sender)
{
_logger.LogDebug($"Removed {item.Title}");
return Task.CompletedTask;
}
public async Task<List<LavalinkTrack>> AwaitSelectionAsync()
{
return await Task.Run(() =>
{
while (!IsConfirmed)
{
if (State == PromptState.INVALID)
throw new InvalidOperationException("Prompt has been Invalidated");
}
IsConfirmed = false;
return SelectedItems;
});
}
protected override DiscordMessageBuilder PopulateMessage(DiscordEmbedBuilder builder)
{
builder.WithTitle(Title);
builder.WithDescription(Common.TrackListString(PageManager.GetPage(CurrentPage), 4000));
List<DiscordEmbed> embeds = new List<DiscordEmbed>();
embeds.Add(builder.Build());
if (Embeds != null)
embeds.AddRange(Embeds);
return new DiscordMessageBuilder().AddEmbeds(embeds);
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Text;
using TomatenMusic.Prompt.Model;
using DSharpPlus;
using System.Threading.Tasks;
using DSharpPlus.EventArgs;
using Microsoft.Extensions.Logging;
using DSharpPlus.Entities;
namespace TomatenMusic.Prompt.Implementation
{
class StringSelectorPrompt : PaginatedSelectPrompt<string>
{
public StringSelectorPrompt(string title, List<string> strings, DiscordPromptBase lastPrompt = null) : base(title, strings, lastPrompt)
{
}
public async override Task<PaginatedSelectMenuOption<string>> ConvertToOption(string item)
{
return new PaginatedSelectMenuOption<string>
{
Label = item
};
}
public async override Task OnSelect(string item, ComponentInteractionCreateEventArgs args, DiscordClient sender)
{
}
public async override Task OnUnselect(string item, ComponentInteractionCreateEventArgs args, DiscordClient sender)
{
}
protected override DiscordMessageBuilder PopulateMessage(DiscordEmbedBuilder builder)
{
foreach (var item in PageManager.GetPage(CurrentPage))
{
builder.AddField(item, item);
}
return new DiscordMessageBuilder().WithEmbed(builder);
}
}
}