ProjectMakoto.Plugins.Music/Commands/MusicModuleAbstractions.cs
2025-04-07 21:33:05 +02:00

192 lines
8.2 KiB
C#

// Project Makoto
// Copyright (C) 2024 Fortunevale
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
using DisCatSharp.Lavalink.Entities;
using DisCatSharp.Lavalink.Enums;
using Xorog.UniversalExtensions;
using Xorog.UniversalExtensions.Enums;
namespace ProjectMakoto.Plugins.Music;
internal static class MusicModuleAbstractions
{
public static async Task<(List<LavalinkTrack> Tracks, LavalinkTrackLoadingResult oriResult, bool Continue)> GetLoadResult(SharedCommandContext ctx, string searchQuery)
{
var CommandKey = ((Entities.Translations)MusicPlugin.Plugin!.Translations).Commands.Music.Play;
if (Regex.IsMatch(searchQuery, "{jndi:(ldap[s]?|rmi):\\/\\/[^\n]+") || searchQuery.Contains("localhost", StringComparison.OrdinalIgnoreCase) || searchQuery.Contains("127.0.0.1", StringComparison.OrdinalIgnoreCase))
throw new Exception();
List<LavalinkTrack> Tracks = new();
var lava = ctx.Client.GetLavalink();
var session = lava.ConnectedSessions.Values.First(x => x.IsConnected);
var embed = new DiscordEmbedBuilder(ctx.ResponseMessage.Embeds[0]);
_ = await ctx.BaseCommand.RespondOrEdit(embed.WithDescription(CommandKey.LookingFor.Get(ctx.DbUser).Build(true, new TVar("Search", searchQuery))).AsLoading(ctx));
LavalinkTrackLoadingResult loadResult;
if (RegexTemplates.YouTubeUrl.IsMatch(searchQuery))
{
if (Regex.IsMatch(searchQuery, @"((\?|&)list=RDMM\w+)(&*)"))
{
Group group = Regex.Match(searchQuery, @"((\?|&)list=RDMM\w+)(&*)", RegexOptions.ExplicitCapture);
var value = group.Value;
if (value.EndsWith('&'))
value = value[..^1];
searchQuery = searchQuery.Replace(value, "");
}
if (Regex.IsMatch(searchQuery, @"((\?|&)start_radio=\d+)(&*)"))
{
Group group = Regex.Match(searchQuery, @"((\?|&)start_radio=\d+)(&*)", RegexOptions.ExplicitCapture);
var value = group.Value;
if (value.EndsWith('&'))
value = value[..^1];
searchQuery = searchQuery.Replace(value, "");
}
var AndIndex = searchQuery.IndexOf('&');
if (!searchQuery.Contains('?') && AndIndex != -1)
{
searchQuery = searchQuery.Remove(AndIndex, 1);
searchQuery = searchQuery.Insert(AndIndex, "?");
}
loadResult = await session.LoadTracksAsync(LavalinkSearchType.Plain, searchQuery);
}
else if (RegexTemplates.SoundcloudUrl.IsMatch(searchQuery))
{
loadResult = await session.LoadTracksAsync(LavalinkSearchType.Plain, searchQuery);
}
else if (RegexTemplates.BandcampUrl.IsMatch(searchQuery))
{
loadResult = await session.LoadTracksAsync(LavalinkSearchType.Plain, searchQuery);
}
else if (RegexTemplates.SpotifyUrl.IsMatch(searchQuery))
{
loadResult = await session.LoadTracksAsync(LavalinkSearchType.Plain, searchQuery);
}
else
{
embed.Description = CommandKey.PlatformSelect.Get(ctx.DbUser).Build(true);
_ = embed.AsAwaitingInput(ctx);
var YouTube = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), "YouTube", false, EmojiTemplates.GetYouTube(ctx.Bot).ToComponent());
var SoundCloud = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), "Soundcloud", false, EmojiTemplates.GetSoundcloud(ctx.Bot).ToComponent());
var Spotify = new DiscordButtonComponent(ButtonStyle.Primary, Guid.NewGuid().ToString(), "Spotify", false, EmojiTemplates.GetSpotify(ctx.Bot).ToComponent());
_ = await ctx.BaseCommand.RespondOrEdit(
new DiscordMessageBuilder().AddEmbed(embed)
.AddComponents(new List<DiscordComponent> { YouTube, SoundCloud, Spotify }));
var Menu1 = await ctx.WaitForButtonAsync(TimeSpan.FromMinutes(2));
if (Menu1.TimedOut)
{
ctx.BaseCommand.ModifyToTimedOut();
return (null, null, false);
}
_ = Menu1.Result.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate);
var platformString = string.Empty;
var searchType = LavalinkSearchType.Plain;
if (Menu1.GetCustomId() == YouTube.CustomId)
{
platformString = "YouTube";
searchType = LavalinkSearchType.Youtube;
}
else if (Menu1.GetCustomId() == SoundCloud.CustomId)
{
platformString = "SoundCloud";
searchType = LavalinkSearchType.SoundCloud;
}
else if (Menu1.GetCustomId() == Spotify.CustomId)
{
platformString = "Spotify";
searchType = LavalinkSearchType.Spotify;
}
_ = await ctx.BaseCommand.RespondOrEdit(embed.WithDescription(CommandKey.LookingFor.Get(ctx.DbUser).Build(true,
new TVar("Search", searchQuery),
new TVar("Platform", platformString))).AsLoading(ctx));
loadResult = await session.LoadTracksAsync(searchType, searchQuery);
}
if (loadResult.LoadType == LavalinkLoadResultType.Error)
{
MusicPlugin.Plugin._logger.LogError("An exception occurred while trying to load lavalink track.");
embed.Description = CommandKey.FailedToLoad.Get(ctx.DbUser).Build(true,
new TVar("Search", searchQuery));
_ = embed.AsError(ctx);
_ = await ctx.BaseCommand.RespondOrEdit(embed.Build());
return (null, loadResult, false);
}
else if (loadResult.LoadType == LavalinkLoadResultType.Empty)
{
embed.Description = CommandKey.NoMatches.Get(ctx.DbUser).Build(true,
new TVar("Search", searchQuery));
_ = embed.AsError(ctx);
_ = await ctx.BaseCommand.RespondOrEdit(embed.Build());
return (null, loadResult, false);
}
else if (loadResult.LoadType == LavalinkLoadResultType.Playlist)
{
return (loadResult.GetResultAs<LavalinkPlaylist>().Tracks.ToList(), loadResult, true);
}
else if (loadResult.LoadType == LavalinkLoadResultType.Track)
{
Tracks.Add(loadResult.GetResultAs<LavalinkTrack>());
return (Tracks, loadResult, true);
}
else if (loadResult.LoadType == LavalinkLoadResultType.Search)
{
var searchResults = loadResult.GetResultAs<List<LavalinkTrack>>();
embed.Description = CommandKey.SearchSuccess.Get(ctx.DbUser).Build(true,
new TVar("Count", searchResults.Count));
_ = embed.AsAwaitingInput(ctx);
_ = await ctx.BaseCommand.RespondOrEdit(embed.Build());
var UriResult = await ctx.BaseCommand.PromptCustomSelection(searchResults
.Select(x => new DiscordStringSelectComponentOption(x.Info.Title.TruncateWithIndication(100), x.Info.Uri.ToString(), $"🔼 {x.Info.Author} | 🕒 {x.Info.Length.GetHumanReadable(TimeFormat.Minutes)}")).ToList());
if (UriResult.TimedOut)
{
ctx.BaseCommand.ModifyToTimedOut();
return (null, loadResult, false);
}
else if (UriResult.Cancelled)
{
return (null, loadResult, false);
}
else if (UriResult.Errored)
{
throw UriResult.Exception;
}
Tracks.Add(searchResults.First(x => x.Info.Uri.ToString() == UriResult.Result));
return (Tracks, loadResult, true);
}
else
{
throw new Exception($"Unknown Load Result Type: {loadResult.LoadType}");
}
}
}