diff --git a/.gitignore b/.gitignore index a069ae1..9491a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -360,5 +360,4 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd -/GitVersion.yml +FodyWeavers.xsd \ No newline at end of file diff --git a/GitVersion.yml b/GitVersion.yml deleted file mode 100644 index af41166..0000000 --- a/GitVersion.yml +++ /dev/null @@ -1,33 +0,0 @@ -mode: ContinuousDelivery -branches: - main: - regex: ^master$|^main$ - mode: ContinuousDelivery - tag: '' - increment: Minor - prevent-increment-of-merged-branch-version: true - track-merge-target: false - source-branches: [ 'develop', 'release' ] - tracks-release-branches: false - is-release-branch: true - is-mainline: true - pre-release-weight: 55000 - develop: - regex: ^dev(elop)?(ment)?$ - mode: ContinuousDeployment - tag: pre - increment: Patch - prevent-increment-of-merged-branch-version: false - track-merge-target: true - source-branches: [] - tracks-release-branches: true - is-release-branch: false - is-mainline: false - pre-release-weight: 0 -ignore: - sha: [] -merge-message-formats: {} -major-version-bump-message: '\+semver:\s?(breaking|major)' -minor-version-bump-message: '\+semver:\s?(feature|minor)' -patch-version-bump-message: '\+semver:\s?(fix|patch)' -commit-message-incrementing: Enabled diff --git a/README.md b/README.md index 3223845..3aa60e7 100644 --- a/README.md +++ b/README.md @@ -2,5 +2,3 @@ Dev ![TeamCity dev build status](https://ci.tomatentum.net/app/rest/builds/build Master ![TeamCity master build status](https://ci.tomatentum.net/app/rest/builds/buildType:id:TomatenMusicV2_Build,branch:name:master/statusIcon.svg) # TomatenMusic - -Project CI can be found [here](https://ci.tomatentum.net/project/TomatenMusicV2 "Tomatentum CI") diff --git a/TomatenMusic/.config/dotnet-tools.json b/TomatenMusic Api/.config/dotnet-tools.json similarity index 100% rename from TomatenMusic/.config/dotnet-tools.json rename to TomatenMusic Api/.config/dotnet-tools.json diff --git a/TomatenMusic/Auth/Controllers/UsersController.cs b/TomatenMusic Api/Auth/Controllers/UsersController.cs similarity index 100% rename from TomatenMusic/Auth/Controllers/UsersController.cs rename to TomatenMusic Api/Auth/Controllers/UsersController.cs diff --git a/TomatenMusic/Auth/Entities/User.cs b/TomatenMusic Api/Auth/Entities/User.cs similarity index 100% rename from TomatenMusic/Auth/Entities/User.cs rename to TomatenMusic Api/Auth/Entities/User.cs diff --git a/TomatenMusic/Auth/Helpers/AppSettings.cs b/TomatenMusic Api/Auth/Helpers/AppSettings.cs similarity index 100% rename from TomatenMusic/Auth/Helpers/AppSettings.cs rename to TomatenMusic Api/Auth/Helpers/AppSettings.cs diff --git a/TomatenMusic/Auth/Helpers/AuthorizeAttribute.cs b/TomatenMusic Api/Auth/Helpers/AuthorizeAttribute.cs similarity index 100% rename from TomatenMusic/Auth/Helpers/AuthorizeAttribute.cs rename to TomatenMusic Api/Auth/Helpers/AuthorizeAttribute.cs diff --git a/TomatenMusic/Auth/Helpers/JwtMiddleware.cs b/TomatenMusic Api/Auth/Helpers/JwtMiddleware.cs similarity index 100% rename from TomatenMusic/Auth/Helpers/JwtMiddleware.cs rename to TomatenMusic Api/Auth/Helpers/JwtMiddleware.cs diff --git a/TomatenMusic/Auth/Models/AuthenticateRequest.cs b/TomatenMusic Api/Auth/Models/AuthenticateRequest.cs similarity index 100% rename from TomatenMusic/Auth/Models/AuthenticateRequest.cs rename to TomatenMusic Api/Auth/Models/AuthenticateRequest.cs diff --git a/TomatenMusic/Auth/Models/AuthenticateResponse.cs b/TomatenMusic Api/Auth/Models/AuthenticateResponse.cs similarity index 100% rename from TomatenMusic/Auth/Models/AuthenticateResponse.cs rename to TomatenMusic Api/Auth/Models/AuthenticateResponse.cs diff --git a/TomatenMusic/Auth/Services/UserService.cs b/TomatenMusic Api/Auth/Services/UserService.cs similarity index 100% rename from TomatenMusic/Auth/Services/UserService.cs rename to TomatenMusic Api/Auth/Services/UserService.cs diff --git a/TomatenMusic/Controllers/PlayerController.cs b/TomatenMusic Api/Controllers/PlayerController.cs similarity index 56% rename from TomatenMusic/Controllers/PlayerController.cs rename to TomatenMusic Api/Controllers/PlayerController.cs index 49d900b..241f606 100644 --- a/TomatenMusic/Controllers/PlayerController.cs +++ b/TomatenMusic Api/Controllers/PlayerController.cs @@ -1,12 +1,9 @@ using DSharpPlus.Entities; using Microsoft.AspNetCore.Mvc; using TomatenMusic; -using TomatenMusic.Music; using TomatenMusic_Api; using TomatenMusic_Api.Auth.Helpers; using TomatenMusic_Api.Models; -using TomatenMusic_Api.Models.EventArgs; -using static TomatenMusic_Api.InProcessEventBus; namespace TomatenMusic_Api.Controllers; @@ -57,9 +54,8 @@ public class PlayerController : ControllerBase } [HttpPost("connect")] - public async Task PostConnect(ChannelConnectRequest request) + public async Task PostConnection(ChannelConnectRequest request) { - try { await _tomatenMusicDataService.GetGuildAsync(request.Guild_Id); @@ -81,7 +77,7 @@ public class PlayerController : ControllerBase try { - channel = await _tomatenMusicDataService.GetDiscordChannelAsync(request.Guild_Id, request.Channel_Id); + channel = await _tomatenMusicDataService.GetDiscordChannelAsync(request.Channel_Id); }catch (Exception ex) { return NotFound("Channel was not Found"); @@ -89,58 +85,8 @@ public class PlayerController : ControllerBase - _eventBus.OnConnectRequestEvent(new ChannelConnectArgs(request.Guild_Id, channel)); + _eventBus.OnConnectRequestEvent(new InProcessEventBus.ChannelConnectEventArgs(request.Guild_Id, channel)); return Ok(); } - - [HttpPost("disconnect")] - public async Task PostDisconnect(ChannelDisconnectRequest request) - { - try - { - await _tomatenMusicDataService.GetGuildAsync(request.GuildId); - } - catch (Exception ex) - { - return NotFound("That Guild was not found"); - } - - if (!await _tomatenMusicDataService.IsConnectedAsync(request.GuildId) == true) - return BadRequest("The Bot is not connected."); - - _eventBus.OnDisconnectRequestEvent(new ChannelDisconnectArgs(request.GuildId)); - return Ok(); - - } - - [HttpPost("play")] - public async Task PostPlay(TrackPlayRequest request) - { - try - { - await _tomatenMusicDataService.GetGuildAsync(request.GuildId); - } - catch (Exception ex) - { - return NotFound("That Guild was not found"); - } - - if (!await _tomatenMusicDataService.IsConnectedAsync(request.GuildId) == true) - return BadRequest("The Bot is not connected."); - - MusicActionResponse response; - - try - { - response = await _tomatenMusicDataService.TrackProvider.SearchAsync(request.TrackUri); - }catch (Exception ex) - { - return NotFound(ex.Message + "\n" + ex.StackTrace); - } - - _eventBus.OnPlayRequestEvent(new TrackPlayArgs(response, request.GuildId, TimeSpan.FromSeconds(request.StartTimeSeconds), request.Now)); - - return Ok(); - } } diff --git a/TomatenMusic/Models/BasicTrackInfo.cs b/TomatenMusic Api/Models/BasicTrackInfo.cs similarity index 91% rename from TomatenMusic/Models/BasicTrackInfo.cs rename to TomatenMusic Api/Models/BasicTrackInfo.cs index d353636..dd245ac 100644 --- a/TomatenMusic/Models/BasicTrackInfo.cs +++ b/TomatenMusic Api/Models/BasicTrackInfo.cs @@ -27,9 +27,9 @@ namespace TomatenMusic_Api.Models Name = track.Title; Platform = ctx.SpotifyIdentifier == null ? TrackPlatform.YOUTUBE : TrackPlatform.SPOTIFY; - YoutubeId = track.TrackIdentifier; + YoutubeId = track.Identifier; SpotifyId = ctx.SpotifyIdentifier; - URL = new Uri(track.Source); + URL = ctx.YoutubeUri; } } diff --git a/TomatenMusic/Models/ChannelConnectRequest.cs b/TomatenMusic Api/Models/ChannelConnectRequest.cs similarity index 100% rename from TomatenMusic/Models/ChannelConnectRequest.cs rename to TomatenMusic Api/Models/ChannelConnectRequest.cs diff --git a/TomatenMusic/Models/PlayerConnectionInfo.cs b/TomatenMusic Api/Models/PlayerConnectionInfo.cs similarity index 100% rename from TomatenMusic/Models/PlayerConnectionInfo.cs rename to TomatenMusic Api/Models/PlayerConnectionInfo.cs diff --git a/TomatenMusic/Program.cs b/TomatenMusic Api/Program.cs similarity index 83% rename from TomatenMusic/Program.cs rename to TomatenMusic Api/Program.cs index a17217f..7a496fc 100644 --- a/TomatenMusic/Program.cs +++ b/TomatenMusic Api/Program.cs @@ -4,9 +4,11 @@ using TomatenMusic_Api.Auth.Services; var builder = WebApplication.CreateBuilder(args); +// Add services to the container. builder.Services.AddControllers(); builder.Services.AddCors(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -22,9 +24,11 @@ builder.Services.AddSingleton(); var app = builder.Build(); // Configure the HTTP request pipeline. -app.UseSwagger(); -app.UseSwaggerUI(); + app.UseSwagger(); + app.UseSwaggerUI(); + +app.UseHttpsRedirection(); app.UseWebSockets(); app.UseCors(x => x diff --git a/TomatenMusic/Properties/launchSettings.json b/TomatenMusic Api/Properties/launchSettings.json similarity index 100% rename from TomatenMusic/Properties/launchSettings.json rename to TomatenMusic Api/Properties/launchSettings.json diff --git a/TomatenMusic Api/Services/EventBus.cs b/TomatenMusic Api/Services/EventBus.cs new file mode 100644 index 0000000..9ec1f8a --- /dev/null +++ b/TomatenMusic Api/Services/EventBus.cs @@ -0,0 +1,30 @@ +using DSharpPlus.Entities; +using Emzi0767.Utilities; +using Microsoft.AspNetCore.Mvc; +using TomatenMusic_Api.Models; + +namespace TomatenMusic_Api; + +public class InProcessEventBus +{ + public event AsyncEventHandler? OnConnectRequest; + + public void OnConnectRequestEvent(ChannelConnectEventArgs e) + { + _ = OnConnectRequest?.Invoke(this, e); + } + + public class ChannelConnectEventArgs : AsyncEventArgs + { + public ulong Guild_Id { get; set; } + + public DiscordChannel Channel { get; set; } + + public ChannelConnectEventArgs(ulong guild_Id, DiscordChannel channel) + { + Guild_Id = guild_Id; + Channel = channel; + } + } +} + diff --git a/TomatenMusic/Services/TomatenMusicDataService.cs b/TomatenMusic Api/Services/TomatenMusicDataService.cs similarity index 79% rename from TomatenMusic/Services/TomatenMusicDataService.cs rename to TomatenMusic Api/Services/TomatenMusicDataService.cs index 53fc3db..b0bef08 100644 --- a/TomatenMusic/Services/TomatenMusicDataService.cs +++ b/TomatenMusic Api/Services/TomatenMusicDataService.cs @@ -11,14 +11,12 @@ namespace TomatenMusic_Api public class TomatenMusicDataService : IHostedService { private ILogger _logger; - private IServiceProvider _serviceProvider { get; set; } = TomatenMusicBot.ServiceProvider; + public IServiceProvider _serviceProvider { get; set; } = TomatenMusicBot.ServiceProvider; public IAudioService _audioService { get; set; } - public TrackProvider TrackProvider { get; set; } public TomatenMusicDataService(ILogger logger) { _logger = logger; _audioService = _serviceProvider.GetRequiredService(); - TrackProvider = _serviceProvider.GetRequiredService(); } public async Task GetConnectionInfoAsync(ulong guild_id) @@ -60,19 +58,18 @@ namespace TomatenMusic_Api return list; } - public Task GetDiscordChannelAsync(ulong guild_id, ulong channel_id) + public Task GetDiscordChannelAsync(ulong channel_id) { - var client = _serviceProvider.GetRequiredService(); - var guildClient = client.GetShard(guild_id); - return guildClient.GetChannelAsync(channel_id); + DiscordClient client = _serviceProvider.GetRequiredService(); + + return client.GetChannelAsync(channel_id); } public Task GetGuildAsync(ulong guild_id) { - var client = _serviceProvider.GetRequiredService(); - var guildClient = client.GetShard(guild_id); + DiscordClient client = _serviceProvider.GetRequiredService(); - return guildClient.GetGuildAsync(guild_id); + return client.GetGuildAsync(guild_id); } public Task StartAsync(CancellationToken cancellationToken) diff --git a/TomatenMusic/Services/TomatenMusicService.cs b/TomatenMusic Api/Services/TomatenMusicService.cs similarity index 54% rename from TomatenMusic/Services/TomatenMusicService.cs rename to TomatenMusic Api/Services/TomatenMusicService.cs index 1ca8fde..28b6f2c 100644 --- a/TomatenMusic/Services/TomatenMusicService.cs +++ b/TomatenMusic Api/Services/TomatenMusicService.cs @@ -2,7 +2,6 @@ using TomatenMusic; using TomatenMusic.Music; using TomatenMusic_Api.Models; -using TomatenMusic_Api.Models.EventArgs; using static TomatenMusic_Api.InProcessEventBus; namespace TomatenMusic_Api @@ -25,48 +24,11 @@ namespace TomatenMusic_Api private void Initialize() { _inProcessEventBus.OnConnectRequest += _inProcessEventBus_OnConnectRequest; - _inProcessEventBus.OnDisconnectRequest += _inProcessEventBus_OnDisconnectRequest; - _inProcessEventBus.OnPlayRequest += _inProcessEventBus_OnPlayRequest; } - private async Task _inProcessEventBus_OnPlayRequest(InProcessEventBus sender, TrackPlayArgs e) - { - GuildPlayer player = _audioService.GetPlayer(e.GuildId); - - if (e.Response.Tracks != null && e.Response.Tracks.Any()) - { - if (e.Now) - await player.PlayNowAsync(e.Response.Tracks); - else - await player.PlayItemAsync(e.Response.Tracks); - - return; - } - - if (e.Response.IsPlaylist) - { - if (e.Now) - await player.PlayNowAsync(e.Response.Playlist); - else - await player.PlayItemAsync(e.Response.Playlist); - }else - { - if (e.Now) - await player.PlayNowAsync(e.Response.Track, e.StartTime); - else - await player.PlayAsync(e.Response.Track, e.StartTime); - } - - } - - private async Task _inProcessEventBus_OnDisconnectRequest(InProcessEventBus sender, ChannelDisconnectArgs e) - { - GuildPlayer player = _audioService.GetPlayer(e.GuildId); - player.DisconnectAsync(); - } - - private async Task _inProcessEventBus_OnConnectRequest(InProcessEventBus sender, ChannelConnectArgs e) + private async Task _inProcessEventBus_OnConnectRequest(InProcessEventBus sender, ChannelConnectEventArgs e) { + _logger.LogInformation("Channel Connected!"); GuildPlayer player = await _audioService.JoinAsync(e.Guild_Id, e.Channel.Id, true); } diff --git a/TomatenMusic/TomatenMusic.csproj b/TomatenMusic Api/TomatenMusic Api.csproj similarity index 85% rename from TomatenMusic/TomatenMusic.csproj rename to TomatenMusic Api/TomatenMusic Api.csproj index d793b10..720b797 100644 --- a/TomatenMusic/TomatenMusic.csproj +++ b/TomatenMusic Api/TomatenMusic Api.csproj @@ -5,6 +5,10 @@ enable enable TomatenMusic_Api + + https://api.nuget.org/v3/index.json; + https://nuget.emzi0767.com/api/v3/index.json + @@ -24,12 +28,12 @@ - - - - + + + + diff --git a/TomatenMusic/appsettings.Development.json b/TomatenMusic Api/appsettings.Development.json similarity index 100% rename from TomatenMusic/appsettings.Development.json rename to TomatenMusic Api/appsettings.Development.json diff --git a/TomatenMusic/appsettings.json b/TomatenMusic Api/appsettings.json similarity index 100% rename from TomatenMusic/appsettings.json rename to TomatenMusic Api/appsettings.json diff --git a/TomatenMusic Api/config.json b/TomatenMusic Api/config.json new file mode 100644 index 0000000..ae772c3 --- /dev/null +++ b/TomatenMusic Api/config.json @@ -0,0 +1,8 @@ +{ + "TOKEN"´: "YOUR_BOT_TOKEN", + "LavaLinkPassword": "", + "SpotifyClientId": "", + "SpotifyClientSecret": "", + "YoutubeApiKey": "" + +} diff --git a/TomatenMusic V2.sln b/TomatenMusic V2.sln index b01aa23..2039acd 100644 --- a/TomatenMusic V2.sln +++ b/TomatenMusic V2.sln @@ -3,30 +3,29 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.1.32228.430 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TomatenMusic Api", "TomatenMusic Api\TomatenMusic Api.csproj", "{DC429A00-E2CC-4E66-A3B9-AE5F6B37E93A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TomatenMusicCore", "TomatenMusicCore\TomatenMusicCore.csproj", "{54481E45-9FE3-4CF3-9CE9-489B678AE472}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A3F84EF2-B7C2-44F0-B392-6824AE96530A}" ProjectSection(SolutionItems) = preProject - GitVersion.yml = GitVersion.yml Readme.md = Readme.md EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TomatenMusic", "TomatenMusic\TomatenMusic.csproj", "{E612AAB3-9A73-47F3-ACA0-D3A4CC627D4E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TomatenMusicCore", "TomatenMusicCore\TomatenMusicCore.csproj", "{40B1E82B-656D-413B-B636-EB0AE84391E2}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E612AAB3-9A73-47F3-ACA0-D3A4CC627D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E612AAB3-9A73-47F3-ACA0-D3A4CC627D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E612AAB3-9A73-47F3-ACA0-D3A4CC627D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E612AAB3-9A73-47F3-ACA0-D3A4CC627D4E}.Release|Any CPU.Build.0 = Release|Any CPU - {40B1E82B-656D-413B-B636-EB0AE84391E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {40B1E82B-656D-413B-B636-EB0AE84391E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {40B1E82B-656D-413B-B636-EB0AE84391E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {40B1E82B-656D-413B-B636-EB0AE84391E2}.Release|Any CPU.Build.0 = Release|Any CPU + {DC429A00-E2CC-4E66-A3B9-AE5F6B37E93A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DC429A00-E2CC-4E66-A3B9-AE5F6B37E93A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DC429A00-E2CC-4E66-A3B9-AE5F6B37E93A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DC429A00-E2CC-4E66-A3B9-AE5F6B37E93A}.Release|Any CPU.Build.0 = Release|Any CPU + {54481E45-9FE3-4CF3-9CE9-489B678AE472}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54481E45-9FE3-4CF3-9CE9-489B678AE472}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54481E45-9FE3-4CF3-9CE9-489B678AE472}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54481E45-9FE3-4CF3-9CE9-489B678AE472}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TomatenMusic/Models/ChannelDisconnectRequest.cs b/TomatenMusic/Models/ChannelDisconnectRequest.cs deleted file mode 100644 index 0e31e6d..0000000 --- a/TomatenMusic/Models/ChannelDisconnectRequest.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TomatenMusic_Api.Models.EventArgs -{ - public class ChannelDisconnectRequest - { - public ulong GuildId { get; set; } - } -} diff --git a/TomatenMusic/Models/EventArgs/ChannelConnectArgs.cs b/TomatenMusic/Models/EventArgs/ChannelConnectArgs.cs deleted file mode 100644 index 64d4d28..0000000 --- a/TomatenMusic/Models/EventArgs/ChannelConnectArgs.cs +++ /dev/null @@ -1,18 +0,0 @@ -using DSharpPlus.Entities; -using Emzi0767.Utilities; - -namespace TomatenMusic_Api.Models.EventArgs -{ - public class ChannelConnectArgs : AsyncEventArgs - { - public ulong Guild_Id { get; set; } - - public DiscordChannel Channel { get; set; } - - public ChannelConnectArgs(ulong guild_Id, DiscordChannel channel) - { - Guild_Id = guild_Id; - Channel = channel; - } - } -} diff --git a/TomatenMusic/Models/EventArgs/ChannelDisconnectArgs.cs b/TomatenMusic/Models/EventArgs/ChannelDisconnectArgs.cs deleted file mode 100644 index 42e4404..0000000 --- a/TomatenMusic/Models/EventArgs/ChannelDisconnectArgs.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Emzi0767.Utilities; - -namespace TomatenMusic_Api.Models.EventArgs -{ - public class ChannelDisconnectArgs : AsyncEventArgs - { - public ulong GuildId { get; set; } - - public ChannelDisconnectArgs(ulong guildId) { GuildId = guildId; } - } - - -} diff --git a/TomatenMusic/Models/EventArgs/TrackPlayArgs.cs b/TomatenMusic/Models/EventArgs/TrackPlayArgs.cs deleted file mode 100644 index cd4b43e..0000000 --- a/TomatenMusic/Models/EventArgs/TrackPlayArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Emzi0767.Utilities; -using Lavalink4NET.Player; -using TomatenMusic.Music; - -namespace TomatenMusic_Api.Models.EventArgs -{ - public class TrackPlayArgs : AsyncEventArgs - { - public MusicActionResponse Response { get; set; } - public ulong GuildId { get; set; } - public TimeSpan StartTime { get; set; } - public bool Now { get; set; } - - public TrackPlayArgs(MusicActionResponse response, ulong guildId, TimeSpan startTime, bool now) - { - Response = response; - GuildId = guildId; - StartTime = startTime; - Now = now; - } - } -} diff --git a/TomatenMusic/Models/TrackPlayRequest.cs b/TomatenMusic/Models/TrackPlayRequest.cs deleted file mode 100644 index 598f3f2..0000000 --- a/TomatenMusic/Models/TrackPlayRequest.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TomatenMusic_Api.Models -{ - public class TrackPlayRequest - { - public ulong GuildId { get; set; } - public string TrackUri { get; set; } - public bool Now { get; set; } - public int StartTimeSeconds { get; set; } - } -} diff --git a/TomatenMusic/Services/EventBus.cs b/TomatenMusic/Services/EventBus.cs deleted file mode 100644 index c58224d..0000000 --- a/TomatenMusic/Services/EventBus.cs +++ /dev/null @@ -1,31 +0,0 @@ -using DSharpPlus.Entities; -using Emzi0767.Utilities; -using Microsoft.AspNetCore.Mvc; -using TomatenMusic_Api.Models; -using TomatenMusic_Api.Models.EventArgs; - -namespace TomatenMusic_Api; - -public class InProcessEventBus -{ - public event AsyncEventHandler? OnConnectRequest; - - public event AsyncEventHandler? OnDisconnectRequest; - - public event AsyncEventHandler OnPlayRequest; - public void OnConnectRequestEvent(ChannelConnectArgs e) - { - _ = OnConnectRequest?.Invoke(this, e); - } - - public void OnDisconnectRequestEvent(ChannelDisconnectArgs e) - { - _ = OnDisconnectRequest?.Invoke(this, e); - } - - public void OnPlayRequestEvent(TrackPlayArgs e) - { - _ = OnPlayRequest?.Invoke(this, e); - } -} - diff --git a/TomatenMusic/config.json b/TomatenMusic/config.json deleted file mode 100644 index 5a3277c..0000000 --- a/TomatenMusic/config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "TOKEN": "TOKEN", - "LavaLinkPassword": " ", - "SpotifyClientId": " ", - "SpotifyClientSecret": " ", - "YoutubeApiKey": " " -} - diff --git a/TomatenMusicCore/Commands/MusicCommands.cs b/TomatenMusicCore/Commands/MusicCommands.cs index 74930ee..da39d31 100644 --- a/TomatenMusicCore/Commands/MusicCommands.cs +++ b/TomatenMusicCore/Commands/MusicCommands.cs @@ -17,7 +17,6 @@ using TomatenMusic.Prompt.Option; using System.Linq; using Lavalink4NET; using Lavalink4NET.Player; -using TomatenMusicCore.Prompt.Implementation; namespace TomatenMusic.Commands { @@ -105,40 +104,18 @@ namespace TomatenMusic.Commands response = await _trackProvider.SearchAsync(query, true); }catch (Exception e) { - await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"❌ Search failed: ``{e.Message}``, ```{e.StackTrace}```")); + await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent($"❌ Search failed: ``{e.Message}``")); return; } - DiscordPromptBase prompt; - - if (!response.IsPlaylist && response.Tracks.Count() == 1) - { - var sPrompt = new SongActionPrompt(response.Tracks.First(), ctx.Member); - prompt = sPrompt; - } - else if (response.IsPlaylist) - { - var sPrompt = new PlaylistSongSelectorPrompt(response.Playlist); - sPrompt.ConfirmCallback = async (tracks) => + var prompt = new SongSelectorPrompt($"Search results for {query}", response.Tracks); + prompt.ConfirmCallback = async (tracks) => { - var selectPrompt = new SongListActionPrompt(tracks, ctx.Member, sPrompt); - await selectPrompt.UseAsync(sPrompt.Interaction, sPrompt.Message); + var selectPrompt = new SongListActionPrompt(tracks, ctx.Member, prompt); + await selectPrompt.UseAsync(prompt.Interaction, prompt.Message); }; - prompt = sPrompt; - } - else - { - var sPrompt = new SongSelectorPrompt($"Search results for {query}", response.Tracks); - sPrompt.ConfirmCallback = async (tracks) => - { - var selectPrompt = new SongListActionPrompt(tracks, ctx.Member, sPrompt); - await selectPrompt.UseAsync(sPrompt.Interaction, sPrompt.Message); - }; - prompt = sPrompt; - } - - await prompt.UseAsync(ctx.Interaction, await ctx.GetOriginalResponseAsync()); + await prompt.UseAsync(ctx.Interaction, await ctx.GetOriginalResponseAsync()); } [SlashCommand("time", "Sets the playing position of the current Song.")] diff --git a/TomatenMusicCore/Commands/PlayCommandGroup.cs b/TomatenMusicCore/Commands/PlayCommandGroup.cs index b7095f8..210a988 100644 --- a/TomatenMusicCore/Commands/PlayCommandGroup.cs +++ b/TomatenMusicCore/Commands/PlayCommandGroup.cs @@ -5,27 +5,28 @@ using Lavalink4NET.Player; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Text; using System.Threading.Tasks; using TomatenMusic.Commands.Checks; using TomatenMusic.Music; using TomatenMusic.Music.Entitites; using TomatenMusic.Util; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Commands { - [SlashCommandGroup("playnow", "Plays the specified Song now and prepends the Current song to the Queue.")] + [SlashCommandGroup("play", "Play a song.")] + public class PlayCommandGroup : ApplicationCommandModule + { + + [SlashCommandGroup("now", "Plays the specified Song now and prepends the Current song to the Queue.")] public class PlayNowGroup : ApplicationCommandModule { public IAudioService _audioService { get; set; } - public ILogger _logger { get; set; } + public ILogger _logger { get; set; } public TrackProvider _trackProvider { get; set; } - public PlayNowGroup(IAudioService audioService, ILogger logger, TrackProvider trackProvider) + public PlayNowGroup(IAudioService audioService, ILogger logger, TrackProvider trackProvider) { _audioService = audioService; _logger = logger; @@ -38,8 +39,6 @@ namespace TomatenMusic.Commands [OnlyGuildCheck] public async Task PlayQueryCommand(InteractionContext ctx, [Option("query", "The song search query.")] string query) { - var sw = Stopwatch.StartNew(); - await ctx.DeferAsync(true); GuildPlayer player = (GuildPlayer)_audioService.GetPlayer(ctx.Guild.Id); @@ -53,11 +52,9 @@ namespace TomatenMusic.Commands catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder() - .WithContent($"❌ An error occured while resolving your query: ``{ex.Message}``, ```{ex.StackTrace}```") + .WithContent($"❌ An error occured while resolving your query: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } try @@ -73,18 +70,16 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while connecting to your Channel: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } } try { - if (response.IsPlaylist) + if (response.isPlaylist) { - ILavalinkPlaylist playlist = response.Playlist; - await player.PlayNowAsync(playlist); + LavalinkPlaylist playlist = response.Playlist; + await player.PlayPlaylistNowAsync(playlist); _ = ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Now Playing:").AddEmbed( Common.AsEmbed(playlist) @@ -93,7 +88,7 @@ namespace TomatenMusic.Commands } else { - TomatenMusicTrack track = response.Track; + LavalinkTrack track = response.Track; _ = ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Playing Now") .AddEmbed(Common.AsEmbed(track, player.PlayerQueue.LoopType, 0))); @@ -106,13 +101,9 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while playing your Query: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - } + } [SlashCommand("file", "Play a song file. (mp3/mp4)")] [UserInVoiceChannelCheck] @@ -120,9 +111,8 @@ namespace TomatenMusic.Commands [OnlyGuildCheck] public async Task PlayFileCommand(InteractionContext ctx, [Option("File", "The File that should be played.")] DiscordAttachment file) { - var sw = Stopwatch.StartNew(); - await ctx.DeferAsync(true); + await ctx.DeferAsync(true); GuildPlayer player = (GuildPlayer)_audioService.GetPlayer(ctx.Guild.Id); @@ -137,9 +127,7 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while resolving your file: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } try @@ -154,9 +142,7 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while connecting to your Channel: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } } @@ -166,19 +152,17 @@ namespace TomatenMusic.Commands .AddEmbed(Common.AsEmbed(track, player.PlayerQueue.LoopType, 0))); await player.PlayNowAsync(response.Track); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - } + } } - [SlashCommandGroup("play", "Queues or plays the Song")] + [SlashCommandGroup("queue", "Queues or plays the Song")] public class PlayQueueGroup : ApplicationCommandModule { public IAudioService _audioService { get; set; } - public ILogger _logger { get; set; } + public ILogger _logger { get; set; } public TrackProvider _trackProvider { get; set; } - public PlayQueueGroup(IAudioService audioService, ILogger logger, TrackProvider trackProvider) + public PlayQueueGroup(IAudioService audioService, ILogger logger, TrackProvider trackProvider) { _audioService = audioService; _logger = logger; @@ -192,9 +176,7 @@ namespace TomatenMusic.Commands [OnlyGuildCheck] public async Task PlayQueryCommand(InteractionContext ctx, [Option("query", "The song search query.")] string query) { - var sw = Stopwatch.StartNew(); - - await ctx.DeferAsync(true); + await ctx.DeferAsync(true); GuildPlayer player = (GuildPlayer)_audioService.GetPlayer(ctx.Guild.Id); @@ -207,11 +189,9 @@ namespace TomatenMusic.Commands catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder() - .WithContent($"❌ An error occured while resolving your query: ``{ex.Message}``, ```{ex.StackTrace}```") + .WithContent($"❌ An error occured while resolving your query: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } try @@ -226,20 +206,18 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while connecting to your Channel: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } } - try + try { - if (response.IsPlaylist) + if (response.isPlaylist) { - ILavalinkPlaylist playlist = response.Playlist; - await player.PlayItemAsync(playlist); + LavalinkPlaylist playlist = response.Playlist; + await player.PlayPlaylistAsync(playlist); - await ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Now Playing:").AddEmbed( + _ = ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent("Now Playing:").AddEmbed( Common.AsEmbed(playlist) )); @@ -251,21 +229,17 @@ namespace TomatenMusic.Commands _ = ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(player.State == PlayerState.NotPlaying ? "Now Playing:" : "Added to Queue") .AddEmbed(Common.AsEmbed(track, player.PlayerQueue.LoopType, player.State == PlayerState.NotPlaying ? 0 : player.PlayerQueue.Queue.Count + 1))); - await player.PlayItemAsync(response.Track); + await player.PlayAsync(response.Track); } } catch (Exception ex) { await ctx.EditResponseAsync(new DiscordWebhookBuilder() - .WithContent($"❌ An error occured while playing your Track: ``{ex.Message}``, ```{ex.StackTrace}```") + .WithContent($"❌ An error occured while playing your Track: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - } + } [SlashCommand("file", "Play a song file. (mp3/mp4)")] [UserInVoiceChannelCheck] @@ -273,9 +247,8 @@ namespace TomatenMusic.Commands [OnlyGuildCheck] public async Task PlayFileCommand(InteractionContext ctx, [Option("File", "The File that should be played.")] DiscordAttachment file) { - var sw = Stopwatch.StartNew(); - await ctx.DeferAsync(true); + await ctx.DeferAsync(true); GuildPlayer player = (GuildPlayer)_audioService.GetPlayer(ctx.Guild.Id); @@ -290,9 +263,7 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while resolving your file: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } try @@ -307,9 +278,7 @@ namespace TomatenMusic.Commands await ctx.EditResponseAsync(new DiscordWebhookBuilder() .WithContent($"❌ An error occured while connecting to your Channel: ``{ex.Message}``") ); - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); - return; + return; } } @@ -318,10 +287,8 @@ namespace TomatenMusic.Commands _ = ctx.EditResponseAsync(new DiscordWebhookBuilder().WithContent(player.State == PlayerState.NotPlaying ? "Now Playing:" : "Added to Queue") .AddEmbed(Common.AsEmbed(track, player.PlayerQueue.LoopType, player.State == PlayerState.NotPlaying ? 0 : player.PlayerQueue.Queue.Count + 1))); - await player.PlayItemAsync(response.Track); - - sw.Stop(); - _logger.LogDebug($"Command {ctx.CommandName} took {sw.ElapsedMilliseconds}ms to execute."); + await player.PlayAsync(response.Track); } } + } } diff --git a/TomatenMusicCore/Music/Entitites/FullTrackContext.cs b/TomatenMusicCore/Music/Entitites/FullTrackContext.cs index 4250914..44b5ee9 100644 --- a/TomatenMusicCore/Music/Entitites/FullTrackContext.cs +++ b/TomatenMusicCore/Music/Entitites/FullTrackContext.cs @@ -8,8 +8,6 @@ using SpotifyAPI.Web; using Lavalink4NET.Player; using Microsoft.Extensions.DependencyInjection; using Lavalink4NET; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music.Entitites { @@ -17,10 +15,11 @@ namespace TomatenMusic.Music.Entitites { public bool IsFile { get; set; } public string YoutubeDescription { get; set; } + public Uri YoutubeUri { get; set; } public IEnumerable YoutubeTags { get; set; } public ulong YoutubeViews { get; set; } public ulong YoutubeLikes { get; set; } - public Uri? YoutubeThumbnail { get; set; } = null; + public Uri YoutubeThumbnail { get; set; } public DateTime YoutubeUploadDate { get; set; } // // Summary: @@ -35,7 +34,7 @@ namespace TomatenMusic.Music.Entitites public int SpotifyPopularity { get; set; } public Uri SpotifyUri { get; set; } - public static async Task PopulateAsync(TomatenMusicTrack track, FullTrack spotifyTrack = null, string spotifyId = null) + public static async Task PopulateAsync(LavalinkTrack track, string spotifyIdentifier = null) { FullTrackContext context = (FullTrackContext)track.Context; @@ -44,19 +43,17 @@ namespace TomatenMusic.Music.Entitites var spotifyService = TomatenMusicBot.ServiceProvider.GetRequiredService(); var youtubeService = TomatenMusicBot.ServiceProvider.GetRequiredService(); - if (spotifyId != null) - context.SpotifyIdentifier = spotifyId; - else if (spotifyTrack != null) - context.SpotifyIdentifier = spotifyTrack.Id; - + context.SpotifyIdentifier = spotifyIdentifier; + context.YoutubeUri = new Uri($"https://youtu.be/{track.TrackIdentifier}"); track.Context = context; + Console.WriteLine(context); await youtubeService.PopulateTrackInfoAsync(track); - await spotifyService.PopulateTrackAsync(track, spotifyTrack); + await spotifyService.PopulateTrackAsync(track); return track; } - public static async Task PopulateTracksAsync(TrackList tracks) + public static async Task> PopulateTracksAsync(IEnumerable tracks) { foreach (var trackItem in tracks) { diff --git a/TomatenMusicCore/Music/Entitites/IPlayableItem.cs b/TomatenMusicCore/Music/Entitites/IPlayableItem.cs deleted file mode 100644 index d322170..0000000 --- a/TomatenMusicCore/Music/Entitites/IPlayableItem.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TomatenMusic.Music; - -namespace TomatenMusicCore.Music.Entities -{ - public interface IPlayableItem - { - public string Title { get; } - Task Play(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true); - Task PlayNow(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false); - - } -} diff --git a/TomatenMusicCore/Music/Entitites/ILavalinkPlaylist.cs b/TomatenMusicCore/Music/Entitites/LavalinkPlaylist.cs similarity index 78% rename from TomatenMusicCore/Music/Entitites/ILavalinkPlaylist.cs rename to TomatenMusicCore/Music/Entitites/LavalinkPlaylist.cs index 6b88c74..33eb033 100644 --- a/TomatenMusicCore/Music/Entitites/ILavalinkPlaylist.cs +++ b/TomatenMusicCore/Music/Entitites/LavalinkPlaylist.cs @@ -5,15 +5,13 @@ using System.Linq; using TomatenMusic.Util; using DSharpPlus.Entities; using Lavalink4NET.Player; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music.Entitites { - public interface ILavalinkPlaylist : IPlayableItem + public interface LavalinkPlaylist { - public string Title { get; } - public TrackList Tracks { get; } + public string Name { get; } + public IEnumerable Tracks { get; } public Uri Url { get; } public string AuthorName { get; set; } public Uri AuthorUri { get; set; } diff --git a/TomatenMusicCore/Music/Entitites/SpotifyPlaylist.cs b/TomatenMusicCore/Music/Entitites/SpotifyPlaylist.cs index 59a5b26..ed4745d 100644 --- a/TomatenMusicCore/Music/Entitites/SpotifyPlaylist.cs +++ b/TomatenMusicCore/Music/Entitites/SpotifyPlaylist.cs @@ -2,15 +2,13 @@ using System; using System.Collections.Generic; using System.Text; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music.Entitites { - public class SpotifyPlaylist : ILavalinkPlaylist + public class SpotifyPlaylist : LavalinkPlaylist { - public string Title { get; } - public TrackList Tracks { get; } + public string Name { get; } + public IEnumerable Tracks { get; } public Uri Url { get; set; } public string AuthorName { get; set; } public Uri AuthorUri { get; set; } @@ -19,47 +17,13 @@ namespace TomatenMusic.Music.Entitites public string Identifier { get; } public Uri AuthorThumbnail { get; set; } - public SpotifyPlaylist(string name, string id, TrackList tracks, Uri uri) + + public SpotifyPlaylist(string name, string id, IEnumerable tracks, Uri uri) { - Title = name; + Name = name; Identifier = id; Tracks = tracks; Url = uri; } - - public async Task Play(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true) - { - await player.PlayerQueue.QueuePlaylistAsync(this); - - - if (player.State == PlayerState.NotPlaying) - { - LavalinkTrack nextTrack = player.PlayerQueue.NextTrack().Track; - await player.PlayAsync(nextTrack); - } - } - - public async Task PlayNow(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false) - { - if (!player.PlayerQueue.Queue.Any()) - player.PlayerQueue.CurrentPlaylist = this; - - if (!withoutQueuePrepend && player.State == PlayerState.Playing) - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(new TomatenMusicTrack(player.PlayerQueue.LastTrack.WithPosition(player.TrackPosition)))); - - - Queue reversedTracks = new Queue(Tracks); - - TomatenMusicTrack track = reversedTracks.Dequeue(); - player.PlayerQueue.LastTrack = track; - await player.PlayAsync(track); - - reversedTracks.Reverse(); - - foreach (var item in reversedTracks) - { - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(item)); - } - } } } diff --git a/TomatenMusicCore/Music/Entitites/TomatenMusicTrack.cs b/TomatenMusicCore/Music/Entitites/TomatenMusicTrack.cs deleted file mode 100644 index 04bc5e3..0000000 --- a/TomatenMusicCore/Music/Entitites/TomatenMusicTrack.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Lavalink4NET.Player; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TomatenMusic.Music; -using TomatenMusic.Prompt.Implementation; - -namespace TomatenMusicCore.Music.Entities -{ - public class TomatenMusicTrack : LavalinkTrack, IPlayableItem - { - - public override TimeSpan Position { get; } - public TomatenMusicTrack - (LavalinkTrack track) - : base(track.Identifier, track.Author, track.Duration, track.IsLiveStream, track.IsSeekable, track.Source, track.Title, track.TrackIdentifier, track.Provider) - { - Context = track.Context; - Position = track.Position; - } - - public string Title => base.Title; - - public async Task Play(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true) - { - - if (player.State == PlayerState.NotPlaying) - { - player.PlayerQueue.LastTrack = this; - await player.PlayAsync(this, startTime, endTime, noReplace); - } - else - player.PlayerQueue.QueueTrack(this); - - } - - public async Task PlayNow(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false) - { - if (!withoutQueuePrepend && player.State == PlayerState.Playing) - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(new TomatenMusicTrack(player.PlayerQueue.LastTrack.WithPosition(player.TrackPosition)))); - - - player.PlayerQueue.LastTrack = this; - await player.PlayAsync(this, startTime, endTime); - } - - } -} diff --git a/TomatenMusicCore/Music/Entitites/TrackList.cs b/TomatenMusicCore/Music/Entitites/TrackList.cs deleted file mode 100644 index 1ff34f4..0000000 --- a/TomatenMusicCore/Music/Entitites/TrackList.cs +++ /dev/null @@ -1,567 +0,0 @@ - - -using Lavalink4NET.Player; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using TomatenMusic.Music; - -namespace TomatenMusicCore.Music.Entities -{ - // - // Summary: - // A thread-safe queue for Lavalink4NET.Player.LavalinkTrack. - public sealed class TrackList : IList, ICollection, IEnumerable, IEnumerable, IPlayableItem - { - private readonly List _list; - - private readonly object _syncRoot; - - // - // Summary: - // Gets the number of queued tracks. - // - // Remarks: - // This property is thread-safe, so it can be used from multiple threads at once - // safely. - public int Count - { - get - { - lock (_syncRoot) - { - return _list.Count; - } - } - } - - // - // Summary: - // Gets a value indicating whether the queue is empty. - // - // Remarks: - // This property is thread-safe, so it can be used from multiple threads at once - // safely. - public bool IsEmpty => Count == 0; - - // - // Summary: - // Gets a value indicating whether the queue is read-only. - // - // Remarks: - // This property is thread-safe, so it can be used from multiple threads at once - // safely. - public bool IsReadOnly => false; - - // - // Summary: - // Gets or sets the enqueued tracks. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public IReadOnlyList Tracks - { - get - { - lock (_syncRoot) - { - return _list.ToArray(); - } - } - set - { - lock (_syncRoot) - { - _list.Clear(); - _list.AddRange(value); - } - } - } - - public string Title => $"Track List with {Count} Tracks"; - - // - // Summary: - // Gets or sets the track at the specified index. - // - // Parameters: - // index: - // the zero-based position - // - // Returns: - // the track at the specified index - // - // Remarks: - // This indexer property is thread-safe, so it can be used from multiple threads - // at once safely. - public TomatenMusicTrack this[int index] - { - get - { - lock (_syncRoot) - { - return _list[index]; - } - } - set - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - lock (_syncRoot) - { - _list[index] = value; - } - } - } - - - public TrackList() - { - _list = new List(); - _syncRoot = new object(); - } - - public TrackList(IEnumerable tracks) - { - _list = new List(); - _syncRoot = new object(); - - foreach (var track in tracks) - Add(new TomatenMusicTrack(track)); - } - - // - // Summary: - // Adds a track at the end of the queue. - // - // Parameters: - // track: - // the track to add - // - // Exceptions: - // T:System.ArgumentNullException: - // thrown if the specified track is null. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void Add(TomatenMusicTrack track) - { - if (track == null) - { - throw new ArgumentNullException("track"); - } - - lock (_syncRoot) - { - _list.Add(track); - } - } - - // - // Summary: - // Adds all specified tracks to the queue. - // - // Parameters: - // tracks: - // the tracks to enqueue - // - // Exceptions: - // T:System.ArgumentNullException: - // thrown if the specified tracks enumerable is null. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void AddRange(IEnumerable tracks) - { - if (tracks == null) - { - throw new ArgumentNullException("tracks"); - } - - lock (_syncRoot) - { - _list.AddRange(tracks); - } - } - - // - // Summary: - // Clears all tracks from the queue. - // - // Returns: - // the number of tracks removed - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public int Clear() - { - lock (_syncRoot) - { - int count = _list.Count; - _list.Clear(); - return count; - } - } - - // - // Summary: - // Gets a value indicating whether the specified track is in the queue. - // - // Parameters: - // track: - // the track to find - // - // Returns: - // a value indicating whether the specified track is in the queue - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public bool Contains(TomatenMusicTrack track) - { - if (track == null) - { - throw new ArgumentNullException("track"); - } - - lock (_syncRoot) - { - return _list.Contains(track); - } - } - - // - // Summary: - // Copies all tracks to the specified array at the specified index. - // - // Parameters: - // array: - // the array to the tracks to - // - // index: - // the zero-based writing start index - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void CopyTo(TomatenMusicTrack[] array, int index) - { - lock (_syncRoot) - { - _list.CopyTo(array, index); - } - } - - // - // Summary: - // Dequeues a track using the FIFO method. - // - // Returns: - // the dequeued track - // - // Exceptions: - // T:System.InvalidOperationException: - // thrown if no tracks were in the queue - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public TomatenMusicTrack Dequeue() - { - lock (_syncRoot) - { - if (_list.Count <= 0) - { - throw new InvalidOperationException("No tracks in to dequeue."); - } - - TomatenMusicTrack result = _list[0]; - _list.RemoveAt(0); - return result; - } - } - - // - // Summary: - // Deletes all duplicate tracks from the queue. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void Distinct() - { - lock (_syncRoot) - { - if (_list.Count > 1) - { - TomatenMusicTrack[] collection = (from track in _list - group track by track.Identifier into s - select s.First()).ToArray(); - _list.Clear(); - _list.AddRange(collection); - } - } - } - - // - // Summary: - // Gets the track enumerator. - // - // Returns: - // the track enumerator - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public IEnumerator GetEnumerator() - { - lock (_syncRoot) - { - return _list.ToList().GetEnumerator(); - } - } - - // - // Summary: - // Gets the zero-based index of the specified track. - // - // Parameters: - // track: - // the track to locate - // - // Returns: - // the zero-based index of the specified track - // - // Exceptions: - // T:System.ArgumentNullException: - // thrown if the specified track is null. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public int IndexOf(TomatenMusicTrack track) - { - if (track == null) - { - throw new ArgumentNullException("track"); - } - - lock (_syncRoot) - { - return _list.IndexOf(track); - } - } - - // - // Summary: - // Inserts the specified track at the specified index. - // - // Parameters: - // index: - // the zero-based index to insert (e.g. 0 = top) - // - // track: - // the track to insert - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void Insert(int index, TomatenMusicTrack track) - { - lock (_syncRoot) - { - _list.Insert(index, track); - } - } - - // - // Summary: - // Tries to remove the specified track from the queue. - // - // Parameters: - // track: - // the track to remove - // - // Returns: - // a value indicating whether the track was found and removed from the queue - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public bool Remove(TomatenMusicTrack track) - { - lock (_syncRoot) - { - return _list.Remove(track); - } - } - - // - // Summary: - // Removes all tracks that matches the specified predicate. - // - // Parameters: - // predicate: - // the track predicate - // - // Returns: - // the number of tracks removed - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public int RemoveAll(Predicate predicate) - { - lock (_syncRoot) - { - return _list.RemoveAll(predicate); - } - } - - // - // Summary: - // Removes a track at the specified index. - // - // Parameters: - // index: - // the index to remove the track - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void RemoveAt(int index) - { - lock (_syncRoot) - { - _list.RemoveAt(index); - } - } - - // - // Summary: - // Removes all count tracks from the specified index. - // - // Parameters: - // index: - // the start index (zero-based) - // - // count: - // the number of tracks to remove - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void RemoveRange(int index, int count) - { - lock (_syncRoot) - { - _list.RemoveRange(index, count); - } - } - - // - // Summary: - // Shuffles / mixes all tracks in the queue. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public void Shuffle() - { - lock (_syncRoot) - { - if (_list.Count > 2) - { - TomatenMusicTrack[] collection = _list.OrderBy((TomatenMusicTrack s) => Guid.NewGuid()).ToArray(); - _list.Clear(); - _list.AddRange(collection); - } - } - } - - // - // Summary: - // Tries to dequeue a track using the FIFO method. - // - // Parameters: - // track: - // the dequeued track; or default is the result is false. - // - // Returns: - // a value indicating whether a track was dequeued. - // - // Exceptions: - // T:System.InvalidOperationException: - // thrown if no tracks were in the queue - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - public bool TryDequeue(out TomatenMusicTrack? track) - { - lock (_syncRoot) - { - if (_list.Count <= 0) - { - track = null; - return false; - } - - track = _list[0]; - _list.RemoveAt(0); - return true; - } - } - - // - // Summary: - // Clears the queue. - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - void ICollection.Clear() - { - lock (_syncRoot) - { - _list.Clear(); - } - } - - // - // Summary: - // Gets the track enumerator. - // - // Returns: - // the track enumerator - // - // Remarks: - // This method is thread-safe, so it can be used from multiple threads at once safely. - IEnumerator IEnumerable.GetEnumerator() - { - lock (_syncRoot) - { - return _list.ToArray().GetEnumerator(); - } - } - - public async Task Play(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true) - { - await player.PlayerQueue.QueueTracksAsync(this); - - if (player.State == PlayerState.NotPlaying) - { - LavalinkTrack nextTrack = player.PlayerQueue.NextTrack().Track; - await player.PlayAsync(nextTrack, startTime, endTime, noReplace); - } - } - - public async Task PlayNow(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false) - { - Queue reversedTracks = new Queue(this); - - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(new TomatenMusicTrack(player.PlayerQueue.LastTrack.WithPosition(player.TrackPosition)))); - - TomatenMusicTrack track = reversedTracks.Dequeue(); - player.PlayerQueue.LastTrack = track; - await player.PlayAsync(track, startTime, endTime); - - reversedTracks.Reverse(); - - foreach (var item in reversedTracks) - { - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(item)); - } - } - } -} diff --git a/TomatenMusicCore/Music/Entitites/YoutubePlaylist.cs b/TomatenMusicCore/Music/Entitites/YoutubePlaylist.cs index 0da7007..2a35419 100644 --- a/TomatenMusicCore/Music/Entitites/YoutubePlaylist.cs +++ b/TomatenMusicCore/Music/Entitites/YoutubePlaylist.cs @@ -4,18 +4,14 @@ using System.Text; using System.Linq; using Google.Apis.YouTube.v3.Data; using Lavalink4NET.Player; -using Microsoft.Extensions.DependencyInjection; -using TomatenMusic.Services; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music.Entitites { - public class YoutubePlaylist : ILavalinkPlaylist + public class YoutubePlaylist : LavalinkPlaylist { - public string Title { get; } + public string Name { get; } - public TrackList Tracks { get; } + public IEnumerable Tracks { get; } public int TrackCount { get; } @@ -30,50 +26,13 @@ namespace TomatenMusic.Music.Entitites public Playlist YoutubeItem { get; set; } public Uri AuthorThumbnail { get; set; } - public YoutubePlaylist(string name, TrackList tracks, string id) + public YoutubePlaylist(string name, IEnumerable tracks, Uri uri) { - Identifier = id; - Title = name; + Identifier = uri.ToString().Replace("https://www.youtube.com/playlist?list=", ""); + Name = name; Tracks = tracks; - Url = new Uri($"https://youtube.com/playlist?list={id}"); + Url = uri; TrackCount = tracks.Count(); - - } - - public async Task Play(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true) - { - await player.PlayerQueue.QueuePlaylistAsync(this); - - - if (player.State == PlayerState.NotPlaying) - { - LavalinkTrack nextTrack = player.PlayerQueue.NextTrack().Track; - await player.PlayAsync(nextTrack); - } - } - - public async Task PlayNow(GuildPlayer player, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false) - { - if (!player.PlayerQueue.Queue.Any()) - player.PlayerQueue.CurrentPlaylist = this; - - if (!withoutQueuePrepend && player.State == PlayerState.Playing) - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(new TomatenMusicTrack(player.PlayerQueue.LastTrack.WithPosition(player.TrackPosition)))); - - - - Queue reversedTracks = new Queue(Tracks); - - TomatenMusicTrack track = reversedTracks.Dequeue(); - player.PlayerQueue.LastTrack = track; - await player.PlayAsync(track); - - reversedTracks.Reverse(); - - foreach (var item in reversedTracks) - { - player.PlayerQueue.Queue = new Queue(player.PlayerQueue.Queue.Prepend(item)); - } } } } diff --git a/TomatenMusicCore/Music/GuildPlayer.cs b/TomatenMusicCore/Music/GuildPlayer.cs index 1b6e22a..9942bd1 100644 --- a/TomatenMusicCore/Music/GuildPlayer.cs +++ b/TomatenMusicCore/Music/GuildPlayer.cs @@ -15,8 +15,6 @@ using Lavalink4NET; using Lavalink4NET.Rest; using Microsoft.Extensions.DependencyInjection; using Lavalink4NET.Decoding; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music { @@ -41,41 +39,126 @@ namespace TomatenMusic.Music _spotify = serviceProvider.GetRequiredService(); _audioService = serviceProvider.GetRequiredService(); } - public async Task PlayItemAsync(IPlayableItem item, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true) + + public async override Task PlayAsync(LavalinkTrack track, TimeSpan? startTime = null, TimeSpan? endTime = null, bool noReplace = true) { EnsureConnected(); EnsureNotDestroyed(); - _ = item.Play(this, startTime, endTime, noReplace); - _logger.LogInformation("Started playing Item {0} on Guild {1}", item.Title, (await GetGuildAsync()).Name); + if (State == PlayerState.NotPlaying) + { + PlayerQueue.LastTrack = track; + await base.PlayAsync(track, startTime, endTime, noReplace); + _logger.LogInformation("Started playing Track {0} on Guild {1}", track.Title, (await GetGuildAsync()).Name); + }else + PlayerQueue.QueueTrack(track); QueuePrompt.UpdateFor(GuildId); } - public async Task PlayNowAsync(IPlayableItem item, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false) + public async Task PlayNowAsync(LavalinkTrack track, TimeSpan? startTime = null, TimeSpan? endTime = null, bool withoutQueuePrepend = false) { + EnsureConnected(); EnsureNotDestroyed(); - _ = item.PlayNow(this, startTime, endTime, withoutQueuePrepend); - _logger.LogInformation("Started playing Item {0} now on Guild {1}", item.Title, (await GetGuildAsync()).Name); + if (!withoutQueuePrepend) + PlayerQueue.Queue = new Queue(PlayerQueue.Queue.Prepend(PlayerQueue.LastTrack)); + + PlayerQueue.LastTrack = track; + await base.PlayAsync(track, startTime, endTime); + _logger.LogInformation("Started playing Track {0} now on Guild {1}", track.Title, (await GetGuildAsync()).Name); + + + QueuePrompt.UpdateFor(GuildId); + } + + public async Task PlayTracksAsync(List tracks) + { + EnsureNotDestroyed(); + EnsureConnected(); + + _logger.LogInformation("Started playing TrackList {0} on Guild {1}", tracks.ToString(), (await GetGuildAsync()).Name); + + await PlayerQueue.QueueTracksAsync(tracks); + + if (State == PlayerState.NotPlaying) + { + LavalinkTrack nextTrack = PlayerQueue.NextTrack().Track; + await base.PlayAsync(nextTrack); + } + QueuePrompt.UpdateFor(GuildId); + } + public async Task PlayTracksNowAsync(IEnumerable tracks) + { + + EnsureConnected(); + EnsureNotDestroyed(); + Queue reversedTracks = new Queue(tracks); + + LavalinkTrack track = reversedTracks.Dequeue(); + PlayerQueue.LastTrack = track; + await base.PlayAsync(track); + _logger.LogInformation("Started playing Track {0} on Guild {1}", track.Title, (await GetGuildAsync()).Name); + + reversedTracks.Reverse(); + + foreach (var item in reversedTracks) + { + PlayerQueue.Queue = new Queue(PlayerQueue.Queue.Prepend(PlayerQueue.LastTrack)); + } + + QueuePrompt.UpdateFor(GuildId); + } + + public async Task PlayPlaylistAsync(LavalinkPlaylist playlist) + { + EnsureNotDestroyed(); + EnsureConnected(); + + _logger.LogInformation("Started playing Playlist {0} on Guild {1}", playlist.Name, (await GetGuildAsync()).Name); + + await PlayerQueue.QueuePlaylistAsync(playlist); + + + if (State == PlayerState.NotPlaying) + { + LavalinkTrack nextTrack = PlayerQueue.NextTrack().Track; + await base.PlayAsync(nextTrack); + } + QueuePrompt.UpdateFor(GuildId); + } + + public async Task PlayPlaylistNowAsync(LavalinkPlaylist playlist) + { + + EnsureConnected(); + EnsureNotDestroyed(); + if (!PlayerQueue.Queue.Any()) + PlayerQueue.CurrentPlaylist = playlist; + + Queue reversedTracks = new Queue(playlist.Tracks); + + LavalinkTrack track = reversedTracks.Dequeue(); + PlayerQueue.LastTrack = track; + await base.PlayAsync(track); + _logger.LogInformation("Started playing Track {0} on Guild {1}", track.Title, (await GetGuildAsync()).Name); + + reversedTracks.Reverse(); + + foreach (var item in reversedTracks) + { + PlayerQueue.Queue = new Queue(PlayerQueue.Queue.Prepend(PlayerQueue.LastTrack)); + } QueuePrompt.UpdateFor(GuildId); } public async Task RewindAsync() { - EnsureNotDestroyed(); - EnsureConnected(); - if (Position.Position.Seconds > 5) - { - await ReplayAsync(); - return; - } - MusicActionResponse response = PlayerQueue.Rewind(); - + _logger.LogInformation($"Rewinded Track {CurrentTrack.Title} for Track {response.Track.Title}"); await base.PlayAsync(response.Track); QueuePrompt.UpdateFor(GuildId); @@ -83,25 +166,10 @@ namespace TomatenMusic.Music public async Task SkipAsync() { - EnsureNotDestroyed(); - EnsureConnected(); - - MusicActionResponse response; - try - { - response = PlayerQueue.NextTrack(true, Autoplay); - }catch (Exception ex) - { - if (Autoplay) - { - _ = OnAutoPlay(CurrentTrack); - return; - } - throw ex; - } + MusicActionResponse response = PlayerQueue.NextTrack(true); _logger.LogInformation($"Skipped Track {CurrentTrack.Title} for Track {response.Track.Title}"); - await PlayNowAsync(response.Track, withoutQueuePrepend: true); + await base.PlayAsync(response.Track); QueuePrompt.UpdateFor(GuildId); } @@ -159,16 +227,10 @@ namespace TomatenMusic.Music if (channel.Type == ChannelType.Stage) { - DiscordStageInstance stageInstance; - try - { - stageInstance = await channel.GetStageInstanceAsync(); + DiscordStageInstance stageInstance = await channel.GetStageInstanceAsync(); - }catch (Exception ex) - { + if (stageInstance == null) stageInstance = await channel.CreateStageInstanceAsync("Music"); - } - await stageInstance.Channel.UpdateCurrentUserVoiceStateAsync(false); } @@ -194,16 +256,10 @@ namespace TomatenMusic.Music await base.SeekPositionAsync(timeSpan); QueuePrompt.UpdateFor(GuildId); } - protected override void Dispose(bool disposing) - { - QueuePrompt.InvalidateFor(GuildId); - - base.Dispose(disposing); - } - public async override Task OnTrackEndAsync(TrackEndEventArgs eventArgs) { DisconnectOnStop = false; + YoutubeService youtube = TomatenMusicBot.ServiceProvider.GetRequiredService(); var oldTrack = CurrentTrack; if (eventArgs.Reason != TrackEndReason.Finished) @@ -221,35 +277,30 @@ namespace TomatenMusic.Music if (!Autoplay) { _logger.LogInformation("Track has ended and Queue was Empty... Idling"); - QueuePrompt.UpdateFor(GuildId); await base.OnTrackEndAsync(eventArgs); return; } - await base.OnTrackEndAsync(eventArgs); - _ = OnAutoPlay(oldTrack); + LavalinkTrack newTrack = await youtube.GetRelatedTrackAsync(oldTrack.TrackIdentifier); + _logger.LogInformation($"Autoplaying for track {oldTrack.TrackIdentifier} with Track {newTrack.TrackIdentifier}"); + await PlayNowAsync(newTrack, withoutQueuePrepend: true); + /* try + { + LavalinkTrack track = await youtube.GetRelatedTrackAsync(eventArgs.TrackIdentifier); + _logger.LogInformation($"Autoplaying for track {eventArgs.TrackIdentifier} with Track {track.TrackIdentifier}"); + await PlayAsync(track); + } + catch (Exception ex2) + { + await base.OnTrackEndAsync(eventArgs); + }*/ } } } - public async Task OnAutoPlay(LavalinkTrack oldTrack) - { - YoutubeService youtube = TomatenMusicBot.ServiceProvider.GetRequiredService(); - - TomatenMusicTrack newTrack; - if (oldTrack.Provider != StreamProvider.YouTube) - newTrack = await youtube.GetRelatedTrackAsync(PlayerQueue.PlayedTracks.First(x => x.Provider == StreamProvider.YouTube).TrackIdentifier, PlayerQueue.PlayedTracks.Take(5).ToList().ConvertAll(x => x.TrackIdentifier)); - else - newTrack = await youtube.GetRelatedTrackAsync(oldTrack.TrackIdentifier, PlayerQueue.PlayedTracks.Take(5).ToList().ConvertAll(x => x.TrackIdentifier)); - _logger.LogInformation($"Autoplaying for track {oldTrack.TrackIdentifier} with Track {newTrack.TrackIdentifier}"); - PlayerQueue.LastTrack = newTrack; - await newTrack.PlayNow(this, withoutQueuePrepend: true); - QueuePrompt.UpdateFor(GuildId); - } - public async Task GetChannelAsync() { EnsureConnected(); diff --git a/TomatenMusicCore/Music/MusicActionResponse.cs b/TomatenMusicCore/Music/MusicActionResponse.cs index 17cd5ff..2c58b47 100644 --- a/TomatenMusicCore/Music/MusicActionResponse.cs +++ b/TomatenMusicCore/Music/MusicActionResponse.cs @@ -3,29 +3,21 @@ using System; using System.Collections.Generic; using System.Text; using TomatenMusic.Music.Entitites; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music { public class MusicActionResponse { - public ILavalinkPlaylist Playlist { get; } - public TomatenMusicTrack Track { get; } - public TrackList Tracks { get; } - public bool IsPlaylist { get; } - public MusicActionResponse(TomatenMusicTrack track = null, ILavalinkPlaylist playlist = null, TrackList tracks = null) + public LavalinkPlaylist Playlist { get; } + public LavalinkTrack Track { get; } + public IEnumerable Tracks { get; } + public bool isPlaylist { get; } + public MusicActionResponse(LavalinkTrack track = null, LavalinkPlaylist playlist = null, IEnumerable tracks = null) { Playlist = playlist; Track = track; - IsPlaylist = playlist != null; + isPlaylist = playlist != null; Tracks = tracks; - if (track != null) - { - var list = new TrackList(); - list.Add(track); - Tracks = list; - } } } } diff --git a/TomatenMusicCore/Music/PlayerQueue.cs b/TomatenMusicCore/Music/PlayerQueue.cs index 8cff94a..ce90a26 100644 --- a/TomatenMusicCore/Music/PlayerQueue.cs +++ b/TomatenMusicCore/Music/PlayerQueue.cs @@ -9,26 +9,24 @@ using TomatenMusic.Util; using Microsoft.Extensions.Logging; using Lavalink4NET.Player; using Microsoft.Extensions.DependencyInjection; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music { public class PlayerQueue { - public Queue Queue { get; set; } = new Queue(); - public Queue PlayedTracks { get; set; } = new Queue(); + public Queue Queue { get; set; } = new Queue(); + public Queue PlayedTracks { get; set; } = new Queue(); public ILogger _logger { get; set; } = TomatenMusicBot.ServiceProvider.GetRequiredService>(); - public ILavalinkPlaylist CurrentPlaylist { get; set; } + public LavalinkPlaylist CurrentPlaylist { get; set; } public LoopType LoopType { get; private set; } = LoopType.NONE; - public TomatenMusicTrack LastTrack { get; set; } + public LavalinkTrack LastTrack { get; set; } - public List QueueLoopList { get; private set; } = new List(); + public List QueueLoopList { get; private set; } - public void QueueTrack(TomatenMusicTrack track) + public void QueueTrack(LavalinkTrack track) { CurrentPlaylist = null; Queue.Enqueue(track); @@ -38,17 +36,15 @@ namespace TomatenMusic.Music QueueLoopList.Add(track); } - public Task QueuePlaylistAsync(ILavalinkPlaylist playlist) + public Task QueuePlaylistAsync(LavalinkPlaylist playlist) { return Task.Run(() => { - if (CurrentPlaylist == null && Queue.Count == 0) + if (CurrentPlaylist == null) CurrentPlaylist = playlist; - else - CurrentPlaylist = null; - _logger.LogInformation("Queued Playlist {0}", playlist.Title); - foreach (var track in playlist.Tracks) + _logger.LogInformation("Queued Playlist {0}", playlist.Name); + foreach (LavalinkTrack track in playlist.Tracks) { Queue.Enqueue(track); } @@ -61,13 +57,13 @@ namespace TomatenMusic.Music } - public Task QueueTracksAsync(TrackList tracks) + public Task QueueTracksAsync(List tracks) { return Task.Run(() => { CurrentPlaylist = null; _logger.LogInformation("Queued TrackList {0}", tracks.ToString()); - foreach (var track in tracks) + foreach (LavalinkTrack track in tracks) { Queue.Enqueue(track); } @@ -86,17 +82,16 @@ namespace TomatenMusic.Music public void RemoveAt(int index) { if (Queue.Count == 0) throw new InvalidOperationException("Queue was Empty"); - List tracks = Queue.ToList(); + List tracks = Queue.ToList(); tracks.RemoveAt(index); - Queue = new Queue(tracks); + Queue = new Queue(tracks); } - public MusicActionResponse NextTrack(bool ignoreLoop = false, bool autoplay = false) + public MusicActionResponse NextTrack(bool ignoreLoop = false) { if (LastTrack != null) - if (LoopType != LoopType.TRACK || (ignoreLoop && (Queue.Any() || autoplay))) - PlayedTracks = new Queue(PlayedTracks.Prepend(new TomatenMusicTrack(LastTrack.WithPosition(TimeSpan.Zero)))); + PlayedTracks = new Queue(PlayedTracks.Prepend(LastTrack)); switch (LoopType) { @@ -118,9 +113,9 @@ namespace TomatenMusic.Music if (!Queue.Any()) { if (CurrentPlaylist != null) - Queue = new Queue(CurrentPlaylist.Tracks); + Queue = new Queue(CurrentPlaylist.Tracks); else - Queue = new Queue(QueueLoopList); + Queue = new Queue(QueueLoopList); } LastTrack = Queue.Dequeue(); @@ -136,7 +131,7 @@ namespace TomatenMusic.Music if (!PlayedTracks.Any()) throw new InvalidOperationException("There are no songs that could be rewinded to yet."); - Queue = new Queue(Queue.Prepend(LastTrack)); + Queue = new Queue(Queue.Prepend(LastTrack)); LastTrack = PlayedTracks.Dequeue(); return new MusicActionResponse(LastTrack); @@ -146,9 +141,9 @@ namespace TomatenMusic.Music { if (Queue.Count == 0) throw new InvalidOperationException("Queue is Empty"); - List tracks = new List(Queue); + List tracks = new List(Queue); tracks.Shuffle(); - Queue = new Queue(tracks); + Queue = new Queue(tracks); return Task.CompletedTask; } @@ -158,7 +153,8 @@ namespace TomatenMusic.Music if (type == LoopType.QUEUE) { - QueueLoopList = new List(Queue.Prepend(LastTrack)); + QueueLoopList = new List(Queue); + QueueLoopList.Add(LastTrack); } } } diff --git a/TomatenMusicCore/Services/TrackProvider.cs b/TomatenMusicCore/Music/TrackProvider.cs similarity index 52% rename from TomatenMusicCore/Services/TrackProvider.cs rename to TomatenMusicCore/Music/TrackProvider.cs index cdba996..652ca9e 100644 --- a/TomatenMusicCore/Services/TrackProvider.cs +++ b/TomatenMusicCore/Music/TrackProvider.cs @@ -5,11 +5,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Web; using TomatenMusic.Music.Entitites; using TomatenMusic.Services; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Music { @@ -17,13 +14,11 @@ namespace TomatenMusic.Music { public ISpotifyService _spotifyService { get; set; } public IAudioService _audioService { get; set; } - public YoutubeService _youtubeService { get; set; } - public TrackProvider(ISpotifyService spotify, IAudioService audioService, YoutubeService youtubeService) + public TrackProvider(ISpotifyService spotify, IAudioService audioService) { _audioService = audioService; _spotifyService = spotify; - _youtubeService = youtubeService; } public async Task SearchAsync(string query, bool withSearchResults = false) @@ -46,34 +41,28 @@ namespace TomatenMusic.Music else loadResult = await _audioService.LoadTracksAsync(query, SearchMode.YouTube); - if (uri != null && uri.AbsolutePath.Contains(".")) - return await SearchAsync(uri); if (loadResult.LoadType == TrackLoadType.LoadFailed) throw new ArgumentException("Track loading failed"); if (loadResult.LoadType == TrackLoadType.NoMatches) throw new FileNotFoundException("Query resulted in no Matches"); - if (ParseTimestamp(query) != null) - loadResult.Tracks[0] = loadResult.Tracks[0].WithPosition((TimeSpan)ParseTimestamp(query)); - if (withSearchResults && loadResult.LoadType == TrackLoadType.SearchResult) { - return new MusicActionResponse(tracks: await FullTrackContext.PopulateTracksAsync(new TrackList(loadResult.Tracks))); + return new MusicActionResponse(tracks: await FullTrackContext.PopulateTracksAsync(loadResult.Tracks)); } if (loadResult.LoadType == TrackLoadType.PlaylistLoaded && !isSearch) return new MusicActionResponse( - playlist: await _youtubeService.PopulatePlaylistAsync( - new YoutubePlaylist(loadResult.PlaylistInfo.Name, await FullTrackContext.PopulateTracksAsync(new TrackList(loadResult.Tracks)), ParseListId(query)))); + playlist: new YoutubePlaylist(loadResult.PlaylistInfo.Name, await FullTrackContext.PopulateTracksAsync(loadResult.Tracks), uri)); else - return new MusicActionResponse(await FullTrackContext.PopulateAsync(new TomatenMusicTrack(loadResult.Tracks.First()))); + return new MusicActionResponse(await FullTrackContext.PopulateAsync(loadResult.Tracks.First())); } public async Task SearchAsync(Uri fileUri) { - var loadResult = new TomatenMusicTrack(await _audioService.GetTrackAsync(fileUri.ToString())); + var loadResult = await _audioService.GetTrackAsync(fileUri.ToString()); loadResult.Context = new FullTrackContext { IsFile = true @@ -86,50 +75,5 @@ namespace TomatenMusic.Music } - public string ParseListId(string url) - { - var uri = new Uri(url, UriKind.Absolute); - - var query = HttpUtility.ParseQueryString(uri.Query); - - var videoId = string.Empty; - - if (query.AllKeys.Contains("list")) - { - videoId = query["list"]; - } - else - { - videoId = uri.Segments.Last(); - } - - return videoId; - } - - public TimeSpan? ParseTimestamp(string url) - { - Uri uri; - try - { - uri = new Uri(url, UriKind.Absolute); - }catch (UriFormatException) - { - return null; - } - - var query = HttpUtility.ParseQueryString(uri.Query); - - int seconds; - - if (query.AllKeys.Contains("t")) - { - seconds = int.Parse(query["t"]); - } - else - return null; - - return TimeSpan.FromSeconds(seconds); - } - } } diff --git a/TomatenMusicCore/Prompt/Buttons/AddToQueueButton.cs b/TomatenMusicCore/Prompt/Buttons/AddToQueueButton.cs index 951296c..a7bda05 100644 --- a/TomatenMusicCore/Prompt/Buttons/AddToQueueButton.cs +++ b/TomatenMusicCore/Prompt/Buttons/AddToQueueButton.cs @@ -9,22 +9,19 @@ using System.Threading.Tasks; using TomatenMusic.Music; using TomatenMusic.Music.Entitites; using Microsoft.Extensions.DependencyInjection; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; -using TomatenMusic.Prompt.Option; namespace TomatenMusic.Prompt.Buttons { class AddToQueueButton : ButtonPromptOption { - public TrackList Tracks { get; set; } + public List Tracks { get; set; } - public AddToQueueButton(TrackList tracks, int row, DiscordMember requestMember) + public AddToQueueButton(List tracks, int row, DiscordMember requestMember) { Tracks = tracks; Emoji = new DiscordComponentEmoji("▶️"); Row = row; - Style = DSharpPlus.ButtonStyle.Secondary; + Style = DSharpPlus.ButtonStyle.Primary; UpdateMethod = (prompt) => { if (requestMember.VoiceState == null || requestMember.VoiceState.Channel == null) @@ -35,7 +32,7 @@ namespace TomatenMusic.Prompt.Buttons Run = async (args, sender, option) => { IAudioService audioService = TomatenMusicBot.ServiceProvider.GetRequiredService(); - GuildPlayer player; + GuildPlayer player;player = audioService.GetPlayer(args.Guild.Id); try { @@ -47,7 +44,7 @@ namespace TomatenMusic.Prompt.Buttons { player = audioService.GetPlayer(args.Guild.Id); } - await player.PlayItemAsync(Tracks); + await player.PlayTracksAsync(Tracks); } catch (Exception ex) { diff --git a/TomatenMusicCore/Prompt/Buttons/PlayNowButton.cs b/TomatenMusicCore/Prompt/Buttons/PlayNowButton.cs deleted file mode 100644 index 48f4eca..0000000 --- a/TomatenMusicCore/Prompt/Buttons/PlayNowButton.cs +++ /dev/null @@ -1,60 +0,0 @@ -using DSharpPlus.Entities; -using Lavalink4NET; -using Microsoft.Extensions.DependencyInjection; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using TomatenMusic; -using TomatenMusic.Music; -using TomatenMusic.Prompt; -using TomatenMusic.Prompt.Option; -using TomatenMusicCore.Music.Entities; - -namespace TomatenMusicCore.Prompt.Buttons -{ - class PlayNowButton : ButtonPromptOption - { - public TrackList Tracks { get; set; } - - public PlayNowButton(TrackList tracks, int row, DiscordMember requestMember) - { - Tracks = tracks; - Emoji = new DiscordComponentEmoji("▶"); - Content = "Now"; - Row = row; - Style = DSharpPlus.ButtonStyle.Secondary; - UpdateMethod = (prompt) => - { - if (requestMember.VoiceState == null || requestMember.VoiceState.Channel == null) - prompt.Disabled = true; - - return Task.FromResult(prompt); - }; - Run = async (args, sender, option) => - { - IAudioService audioService = TomatenMusicBot.ServiceProvider.GetRequiredService(); - GuildPlayer player; - - try - { - try - { - player = await audioService.JoinAsync(args.Guild.Id, ((DiscordMember)args.User).VoiceState.Channel.Id, true); - - } - catch (Exception ex) - { - player = audioService.GetPlayer(args.Guild.Id); - } - await player.PlayNowAsync(Tracks); - } - catch (Exception ex) - { - - } - }; - } - } -} diff --git a/TomatenMusicCore/Prompt/Implementation/PlaylistSongSelectorPrompt.cs b/TomatenMusicCore/Prompt/Implementation/PlaylistSongSelectorPrompt.cs deleted file mode 100644 index 6b3e16a..0000000 --- a/TomatenMusicCore/Prompt/Implementation/PlaylistSongSelectorPrompt.cs +++ /dev/null @@ -1,105 +0,0 @@ -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.Prompt.Option; -using TomatenMusic.Util; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; - -namespace TomatenMusicCore.Prompt.Implementation -{ - class PlaylistSongSelectorPrompt : PaginatedSelectPrompt - { - public bool IsConfirmed { get; set; } - public Func ConfirmCallback { get; set; } = (tracks) => - { - return Task.CompletedTask; - }; - - public ILavalinkPlaylist Playlist { get; private set; } - - public PlaylistSongSelectorPrompt(ILavalinkPlaylist playlist, DiscordPromptBase lastPrompt = null, List 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> ConvertToOption(TomatenMusicTrack item) - { - return Task.FromResult>(new PaginatedSelectMenuOption - { - 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 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 embeds = new List(); - embeds.Add(builder.Build()); - - if (Embeds != null) - embeds.AddRange(Embeds); - - return new DiscordMessageBuilder().AddEmbeds(embeds); - } - } -} diff --git a/TomatenMusicCore/Prompt/Implementation/QueuePrompt.cs b/TomatenMusicCore/Prompt/Implementation/QueuePrompt.cs index 014caff..1c97992 100644 --- a/TomatenMusicCore/Prompt/Implementation/QueuePrompt.cs +++ b/TomatenMusicCore/Prompt/Implementation/QueuePrompt.cs @@ -32,7 +32,7 @@ namespace TomatenMusic.Prompt.Implementation } public static void UpdateFor(ulong guildId) { - _ = Task.Delay(400).ContinueWith(async (task) => + _ = Task.Delay(600).ContinueWith(async (task) => { foreach (var prompt in ActivePrompts) { @@ -93,15 +93,11 @@ namespace TomatenMusic.Prompt.Implementation _ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction")); return; } - - try { await Player.RewindAsync(); - } - catch (Exception ex) + }catch (Exception ex) { - Console.WriteLine(ex); } } @@ -135,18 +131,8 @@ namespace TomatenMusic.Prompt.Implementation _ = args.Interaction.EditOriginalResponseAsync(new DiscordWebhookBuilder().WithContent("Please connect to the bots Channel to use this Interaction")); return; } - try - { - await Player.SkipAsync(); - } - catch (Exception ex) - { - _ = args.Interaction.CreateResponseAsync( - DSharpPlus.InteractionResponseType.ChannelMessageWithSource, - new DiscordInteractionResponseBuilder() - .WithContent($"An Error occurred during this Interaction {ex.Message}")); - } + await Player.SkipAsync(); System.Timers.Timer timer = new System.Timers.Timer(800); timer.Elapsed += (s, args) => @@ -283,10 +269,7 @@ namespace TomatenMusic.Prompt.Implementation protected async override Task GetMessageAsync() { - return new DiscordMessageBuilder() - .AddEmbed(Common.GetQueueEmbed(Player)) - .AddEmbed(await Common.CurrentSongEmbedAsync(Player)) - .AddEmbeds(Embeds); + return new DiscordMessageBuilder().AddEmbed(Common.GetQueueEmbed(Player)).AddEmbed(await Common.CurrentSongEmbedAsync(Player)).AddEmbeds(Embeds); } } } diff --git a/TomatenMusicCore/Prompt/Implementation/SongActionPrompt.cs b/TomatenMusicCore/Prompt/Implementation/SongActionPrompt.cs index 05ba0ba..ba2d4f1 100644 --- a/TomatenMusicCore/Prompt/Implementation/SongActionPrompt.cs +++ b/TomatenMusicCore/Prompt/Implementation/SongActionPrompt.cs @@ -7,29 +7,23 @@ using System.Threading.Tasks; using TomatenMusic.Music.Entitites; using TomatenMusic.Prompt.Buttons; using TomatenMusic.Prompt.Model; -using TomatenMusic.Util; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; -using TomatenMusicCore.Prompt.Buttons; namespace TomatenMusic.Prompt.Implementation { class SongActionPrompt : ButtonPrompt { public LavalinkTrack Track { get; set; } - public SongActionPrompt(TomatenMusicTrack track, DiscordMember requestMember, List embeds = null) + public SongActionPrompt(LavalinkTrack track, DiscordMember requestMember, List embeds = null) { - Embeds = embeds == null ? new List() : embeds; + Embeds = embeds; Track = track; - AddOption(new AddToQueueButton(new TrackList() { track }, 1, requestMember)); - AddOption(new PlayNowButton(new TrackList() { track }, 1, requestMember)); - + AddOption(new AddToQueueButton(new List() { track }, 1, requestMember)); } protected async override Task GetMessageAsync() { - return new DiscordMessageBuilder().AddEmbed(Common.AsEmbed(Track)).AddEmbeds(Embeds); + return new DiscordMessageBuilder().AddEmbeds(Embeds); } } } diff --git a/TomatenMusicCore/Prompt/Implementation/SongListActionPrompt.cs b/TomatenMusicCore/Prompt/Implementation/SongListActionPrompt.cs index f39b339..776adf6 100644 --- a/TomatenMusicCore/Prompt/Implementation/SongListActionPrompt.cs +++ b/TomatenMusicCore/Prompt/Implementation/SongListActionPrompt.cs @@ -11,24 +11,19 @@ using TomatenMusic.Music; using Microsoft.Extensions.Logging; using TomatenMusic.Prompt.Buttons; using Lavalink4NET.Player; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; -using TomatenMusicCore.Prompt.Buttons; namespace TomatenMusic.Prompt.Implementation { class SongListActionPrompt : ButtonPrompt { //TODO - public TrackList Tracks { get; private set; } + public List Tracks { get; private set; } - public SongListActionPrompt(TrackList tracks, DiscordMember requestMember, DiscordPromptBase lastPrompt = null) : base(lastPrompt) + public SongListActionPrompt(List tracks, DiscordMember requestMember, DiscordPromptBase lastPrompt = null) : base(lastPrompt) { Tracks = tracks; AddOption(new AddToQueueButton(tracks, 1, requestMember)); - AddOption(new PlayNowButton(tracks, 1, requestMember)); - } protected override Task GetMessageAsync() @@ -37,7 +32,7 @@ namespace TomatenMusic.Prompt.Implementation DiscordEmbedBuilder builder = new DiscordEmbedBuilder() .WithTitle("What do you want to do with these Tracks?"); - builder.WithDescription(Common.TrackListString(Tracks, 1000)); + builder.WithDescription(Common.TrackListString(Tracks)); return Task.FromResult(new DiscordMessageBuilder().WithEmbed(builder.Build())); } diff --git a/TomatenMusicCore/Prompt/Implementation/SongSelectorPrompt.cs b/TomatenMusicCore/Prompt/Implementation/SongSelectorPrompt.cs index fbb2e46..2f075c4 100644 --- a/TomatenMusicCore/Prompt/Implementation/SongSelectorPrompt.cs +++ b/TomatenMusicCore/Prompt/Implementation/SongSelectorPrompt.cs @@ -12,16 +12,13 @@ using TomatenMusic.Music.Entitites; using TomatenMusic.Music; using System.Linq; using Lavalink4NET.Player; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; -using TomatenMusic.Prompt.Option; namespace TomatenMusic.Prompt.Implementation { sealed class SongSelectorPrompt : PaginatedSelectPrompt { public bool IsConfirmed { get; set; } - public Func ConfirmCallback { get; set; } = (tracks) => + public Func, Task> ConfirmCallback { get; set; } = (tracks) => { return Task.CompletedTask; }; @@ -45,7 +42,7 @@ namespace TomatenMusic.Prompt.Implementation return; } IsConfirmed = true; - _ = ConfirmCallback.Invoke(new TrackList(SelectedItems)); + _ = ConfirmCallback.Invoke(SelectedItems); } }); } @@ -90,7 +87,7 @@ namespace TomatenMusic.Prompt.Implementation { builder.WithTitle(Title); - builder.WithDescription(Common.TrackListString(PageManager.GetPage(CurrentPage), 4000)); + builder.WithDescription(Common.TrackListString(PageManager.GetPage(CurrentPage))); List embeds = new List(); embeds.Add(builder.Build()); diff --git a/TomatenMusicCore/Prompt/Model/DiscordPromptBase.cs b/TomatenMusicCore/Prompt/Model/DiscordPromptBase.cs index a9db352..8a214d4 100644 --- a/TomatenMusicCore/Prompt/Model/DiscordPromptBase.cs +++ b/TomatenMusicCore/Prompt/Model/DiscordPromptBase.cs @@ -23,7 +23,6 @@ namespace TomatenMusic.Prompt.Model public List Options { get; protected set; } = new List(); public DiscordClient _client { get; set; } public DiscordPromptBase LastPrompt { get; protected set; } - public System.Timers.Timer TimeoutTimer { get; set; } protected ILogger _logger { get; set; } @@ -133,16 +132,6 @@ namespace TomatenMusic.Prompt.Model 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) @@ -175,7 +164,6 @@ namespace TomatenMusic.Prompt.Model _client = client.GetShard((ulong)interaction.GuildId); _client.ComponentInteractionCreated += Discord_ComponentInteractionCreated; - ActivePrompts.Add(this); AddGuids(); DiscordWebhookBuilder builder = await GetWebhookMessageAsync(); @@ -183,22 +171,6 @@ namespace TomatenMusic.Prompt.Model 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() diff --git a/TomatenMusicCore/Prompt/Model/PaginatedButtonPrompt.cs b/TomatenMusicCore/Prompt/Model/PaginatedButtonPrompt.cs index 9de7069..3e35fbb 100644 --- a/TomatenMusicCore/Prompt/Model/PaginatedButtonPrompt.cs +++ b/TomatenMusicCore/Prompt/Model/PaginatedButtonPrompt.cs @@ -7,7 +7,8 @@ using TomatenMusic.Util; using DSharpPlus; using DSharpPlus.EventArgs; using Microsoft.Extensions.Logging; -using TomatenMusic.Prompt.Option; + + namespace TomatenMusic.Prompt.Model { @@ -25,7 +26,6 @@ namespace TomatenMusic.Prompt.Model for (int i = 0; i < 9; i++) { int currentNumber = i + 1; - ButtonPromptOption option = new ButtonPromptOption() { Style = DSharpPlus.ButtonStyle.Primary, diff --git a/TomatenMusicCore/Prompt/Model/PaginatedSelectPrompt.cs b/TomatenMusicCore/Prompt/Model/PaginatedSelectPrompt.cs index 421c52d..967fa06 100644 --- a/TomatenMusicCore/Prompt/Model/PaginatedSelectPrompt.cs +++ b/TomatenMusicCore/Prompt/Model/PaginatedSelectPrompt.cs @@ -24,7 +24,7 @@ namespace TomatenMusic.Prompt.Model public PaginatedSelectPrompt(string title, List items, DiscordPromptBase lastPrompt = null, List embeds = null) : base(lastPrompt) { Embeds = embeds; - PageManager = new PageManager(items, 10); + PageManager = new PageManager(items, 25); Title = title; AddOption(new SelectMenuPromptOption { diff --git a/TomatenMusicCore/Prompt/Option/ButtonPromptOption.cs b/TomatenMusicCore/Prompt/Option/ButtonPromptOption.cs index 4d6a6b1..0a9f61f 100644 --- a/TomatenMusicCore/Prompt/Option/ButtonPromptOption.cs +++ b/TomatenMusicCore/Prompt/Option/ButtonPromptOption.cs @@ -8,7 +8,7 @@ using TomatenMusic.Prompt.Option; using TomatenMusic.Prompt.Model; -namespace TomatenMusic.Prompt.Option +namespace TomatenMusic.Prompt { class ButtonPromptOption : IPromptOption { diff --git a/TomatenMusicCore/Prompt/Option/IPromptOption.cs b/TomatenMusicCore/Prompt/Option/IPromptOption.cs index 26e85d1..ed77dd2 100644 --- a/TomatenMusicCore/Prompt/Option/IPromptOption.cs +++ b/TomatenMusicCore/Prompt/Option/IPromptOption.cs @@ -19,5 +19,8 @@ namespace TomatenMusic.Prompt.Option public Func> UpdateMethod { get; set; } public Func Run { get; set; } + + + } } diff --git a/TomatenMusicCore/Services/SpotifyService.cs b/TomatenMusicCore/Services/SpotifyService.cs index bf9814e..8caeb8b 100644 --- a/TomatenMusicCore/Services/SpotifyService.cs +++ b/TomatenMusicCore/Services/SpotifyService.cs @@ -11,9 +11,6 @@ using TomatenMusic.Services; using TomatenMusic.Music; using Lavalink4NET; using Lavalink4NET.Player; -using System.Runtime.Caching; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Services { @@ -21,9 +18,9 @@ namespace TomatenMusic.Services public interface ISpotifyService { public Task ConvertURL(string url); - public Task PopulateSpotifyPlaylistAsync(SpotifyPlaylist playlist, FullPlaylist spotifyPlaylist = null); - public Task PopulateSpotifyAlbumAsync(SpotifyPlaylist playlist, FullAlbum spotifyAlbum = null); - public Task PopulateTrackAsync(LavalinkTrack track, FullTrack spotifyFullTrack = null); + public Task PopulateSpotifyPlaylistAsync(SpotifyPlaylist playlist); + public Task PopulateSpotifyAlbumAsync(SpotifyPlaylist playlist); + public Task PopulateTrackAsync(LavalinkTrack track); } @@ -32,13 +29,10 @@ namespace TomatenMusic.Services public ILogger _logger { get; set; } public IAudioService _audioService { get; set; } - public ObjectCache Cache { get; set; } - public SpotifyService(SpotifyClientConfig config, ILogger logger, IAudioService audioService) : base(config) { _logger = logger; _audioService = audioService; - Cache = MemoryCache.Default; } public async Task ConvertURL(string url) @@ -49,59 +43,49 @@ namespace TomatenMusic.Services .Replace("https://open.spotify.com/playlist/", "") .Substring(0, 22); - _logger.LogDebug($"Starting spotify conversion for: {url}"); - if (url.StartsWith("https://open.spotify.com/track")) { - FullTrack sTrack = Cache.Contains(trackId) ? Cache.Get(trackId) as FullTrack : await Tracks.Get(trackId); + FullTrack sTrack = await Tracks.Get(trackId); _logger.LogInformation($"Searching youtube from spotify with query: {sTrack.Name} {String.Join(" ", sTrack.Artists)}"); - var track = new TomatenMusicTrack( - await _audioService.GetTrackAsync($"{sTrack.Name} {String.Join(" ", sTrack.Artists.ConvertAll(artist => artist.Name))}" - , Lavalink4NET.Rest.SearchMode.YouTube)); + var track = await _audioService.GetTrackAsync($"{sTrack.Name} {String.Join(" ", sTrack.Artists.ConvertAll(artist => artist.Name))}", Lavalink4NET.Rest.SearchMode.YouTube); if (track == null) throw new ArgumentException("This Spotify Track was not found on Youtube"); - Cache.Add(trackId, sTrack, DateTimeOffset.MaxValue); - - return new MusicActionResponse(await FullTrackContext.PopulateAsync(track, sTrack)); + return new MusicActionResponse(await FullTrackContext.PopulateAsync(track, sTrack.Uri)); } else if (url.StartsWith("https://open.spotify.com/album")) { - TrackList tracks = new TrackList(); + List tracks = new List(); - FullAlbum album = Cache.Contains(trackId) ? Cache.Get(trackId) as FullAlbum : await Albums.Get(trackId); + FullAlbum album = await Albums.Get(trackId); foreach (var sTrack in await PaginateAll(album.Tracks)) { _logger.LogInformation($"Searching youtube from spotify with query: {sTrack.Name} {String.Join(" ", sTrack.Artists.ConvertAll(artist => artist.Name))}"); - var track = new TomatenMusicTrack( - await _audioService.GetTrackAsync($"{sTrack.Name} {String.Join(" ", sTrack.Artists.ConvertAll(artist => artist.Name))}" - , Lavalink4NET.Rest.SearchMode.YouTube)); + + var track = await _audioService.GetTrackAsync($"{sTrack.Name} {String.Join(" ", sTrack.Artists.ConvertAll(artist => artist.Name))}", Lavalink4NET.Rest.SearchMode.YouTube); if (track == null) throw new ArgumentException("This Spotify Track was not found on Youtube"); - - tracks.Add(await FullTrackContext.PopulateAsync(track, spotifyId: sTrack.Uri.Replace("spotify:track:", ""))); + + tracks.Add(await FullTrackContext.PopulateAsync(track, sTrack.Uri)); } Uri uri; Uri.TryCreate(url, UriKind.Absolute, out uri); SpotifyPlaylist playlist = new SpotifyPlaylist(album.Name, album.Id, tracks, uri); - await PopulateSpotifyAlbumAsync(playlist, album); - - Cache.Add(trackId, album, DateTimeOffset.MaxValue); + await PopulateSpotifyAlbumAsync(playlist); return new MusicActionResponse(playlist: playlist); } else if (url.StartsWith("https://open.spotify.com/playlist")) { + List tracks = new List(); - TrackList tracks = new TrackList(); - - FullPlaylist spotifyPlaylist = Cache.Contains(trackId) ? Cache.Get(trackId) as FullPlaylist : await Playlists.Get(trackId); + FullPlaylist spotifyPlaylist = await Playlists.Get(trackId); foreach (var sTrack in await PaginateAll(spotifyPlaylist.Tracks)) { @@ -110,84 +94,60 @@ namespace TomatenMusic.Services FullTrack fullTrack = (FullTrack)sTrack.Track; _logger.LogInformation($"Searching youtube from spotify with query: {fullTrack.Name} {String.Join(" ", fullTrack.Artists.ConvertAll(artist => artist.Name))}"); - var track = new TomatenMusicTrack( - await _audioService.GetTrackAsync($"{fullTrack.Name} {String.Join(" ", fullTrack.Artists.ConvertAll(artist => artist.Name))}" - , Lavalink4NET.Rest.SearchMode.YouTube)); + var track = await _audioService.GetTrackAsync($"{fullTrack.Name} {String.Join(" ", fullTrack.Artists.ConvertAll(artist => artist.Name))}", Lavalink4NET.Rest.SearchMode.YouTube); if (track == null) throw new ArgumentException("This Spotify Track was not found on Youtube"); - tracks.Add(await FullTrackContext.PopulateAsync(track, fullTrack)); + tracks.Add(await FullTrackContext.PopulateAsync(track, fullTrack.Uri)); } } Uri uri; Uri.TryCreate(url, UriKind.Absolute, out uri); SpotifyPlaylist playlist = new SpotifyPlaylist(spotifyPlaylist.Name, spotifyPlaylist.Id, tracks, uri); - await PopulateSpotifyPlaylistAsync(playlist, spotifyPlaylist); - - Cache.Add(trackId, spotifyPlaylist, DateTimeOffset.MaxValue); + await PopulateSpotifyPlaylistAsync(playlist); return new MusicActionResponse(playlist: playlist); } return null; } - public async Task PopulateSpotifyPlaylistAsync(SpotifyPlaylist playlist, FullPlaylist spotifyPlaylist = null) + public async Task PopulateSpotifyPlaylistAsync(SpotifyPlaylist playlist) { - FullPlaylist list = spotifyPlaylist; - if (list == null) - list = await this.Playlists.Get(playlist.Identifier); - - string desc = list.Description; - - playlist.Description = desc.Substring(0, Math.Min(desc.Length, 1024)) + (desc.Length > 1020 ? "..." : " "); - if (playlist.Description.Length < 2) - playlist.Description = "None"; - - playlist.AuthorUri = new Uri($"https://open.spotify.com/user/{list.Owner.Id}"); + var list = await this.Playlists.Get(playlist.Identifier); + playlist.Description = list.Description; + playlist.AuthorUri = new Uri(list.Owner.Uri); playlist.AuthorName = list.Owner.DisplayName; playlist.Followers = list.Followers.Total; - playlist.Url = new Uri($"https://open.spotify.com/playlist/{playlist.Identifier}"); - try - { - playlist.AuthorThumbnail = new Uri(list.Owner.Images.First().Url); - } - catch (Exception ex) { } - + playlist.Url = new Uri(list.Uri); + playlist.AuthorThumbnail = new Uri(list.Owner.Images.First().Url); return playlist; } - public async Task PopulateSpotifyAlbumAsync(SpotifyPlaylist playlist, FullAlbum spotifyAlbum = null) + public async Task PopulateSpotifyAlbumAsync(SpotifyPlaylist playlist) { - FullAlbum list = spotifyAlbum; - if (list == null) - list = await this.Albums.Get(playlist.Identifier); - - string desc = list.Label; - - playlist.Description = desc.Substring(0, Math.Min(desc.Length, 1024)) + (desc.Length > 1020 ? "..." : " "); - playlist.AuthorUri = new Uri($"https://open.spotify.com/user/{list.Artists.First().Uri}"); + var list = await this.Albums.Get(playlist.Identifier); + playlist.Description = list.Label; + playlist.AuthorUri = new Uri(list.Artists.First().Uri); playlist.AuthorName = list.Artists.First().Name; playlist.Followers = list.Popularity; - playlist.Url = new Uri($"https://open.spotify.com/album/{playlist.Identifier}"); + playlist.Url = new Uri(list.Uri); return playlist; } - public async Task PopulateTrackAsync(LavalinkTrack track, FullTrack spotifyFullTrack) + public async Task PopulateTrackAsync(LavalinkTrack track) { FullTrackContext context = (FullTrackContext)track.Context; if (context.SpotifyIdentifier == null) return track; - FullTrack spotifyTrack = spotifyFullTrack; - if (spotifyTrack == null) - spotifyTrack = await Tracks.Get(context.SpotifyIdentifier); + var spotifyTrack = await this.Tracks.Get(context.SpotifyIdentifier); context.SpotifyAlbum = spotifyTrack.Album; context.SpotifyArtists = spotifyTrack.Artists; context.SpotifyPopularity = spotifyTrack.Popularity; - context.SpotifyUri = new Uri($"https://open.spotify.com/track/{context.SpotifyIdentifier}"); + context.SpotifyUri = new Uri(spotifyTrack.Uri); track.Context = context; return track; diff --git a/TomatenMusicCore/Services/YoutubeService.cs b/TomatenMusicCore/Services/YoutubeService.cs index 8f8c78b..12bf269 100644 --- a/TomatenMusicCore/Services/YoutubeService.cs +++ b/TomatenMusicCore/Services/YoutubeService.cs @@ -12,8 +12,6 @@ using static TomatenMusic.TomatenMusicBot; using Lavalink4NET.Player; using Microsoft.Extensions.DependencyInjection; using Lavalink4NET; -using TomatenMusicCore.Music; -using TomatenMusicCore.Music.Entities; namespace TomatenMusic.Services { @@ -39,20 +37,13 @@ namespace TomatenMusic.Services if (channel.Statistics.SubscriberCount != null) context.YoutubeAuthorSubs = (ulong) channel.Statistics.SubscriberCount; - context.YoutubeAuthorThumbnail = new Uri(channel.Snippet.Thumbnails.Default__.Url); + context.YoutubeAuthorThumbnail = new Uri(channel.Snippet.Thumbnails.High.Url); context.YoutubeAuthorUri = new Uri($"https://www.youtube.com/channel/{channel.Id}"); - string desc = video.Snippet.Description; - - context.YoutubeDescription = desc.Substring(0, Math.Min(desc.Length, 1024)) + (desc.Length > 1020 ? "..." : " "); + context.YoutubeDescription = video.Snippet.Description; if (video.Statistics.LikeCount != null) context.YoutubeLikes = (ulong) video.Statistics.LikeCount; context.YoutubeTags = video.Snippet.Tags; - - try - { - context.YoutubeThumbnail = new Uri(video.Snippet.Thumbnails.High.Url); - }catch (Exception ex) { } - + context.YoutubeThumbnail = new Uri(video.Snippet.Thumbnails.High.Url); context.YoutubeUploadDate = (DateTime)video.Snippet.PublishedAt; context.YoutubeViews = (ulong)video.Statistics.ViewCount; context.YoutubeCommentCount = video.Statistics.CommentCount; @@ -60,7 +51,7 @@ namespace TomatenMusic.Services return track; } - public async Task> PopulateTrackListAsync(IEnumerable tracks) + public async Task> PopulateMultiTrackListAsync(IEnumerable tracks) { List newTracks = new List(); foreach (var track in tracks) @@ -68,26 +59,19 @@ namespace TomatenMusic.Services return newTracks; } - public async Task PopulatePlaylistAsync(YoutubePlaylist playlist) + public async Task PopulatePlaylistAsync(YoutubePlaylist playlist) { var list = await GetPlaylistAsync(playlist.Identifier); var channel = await GetChannelAsync(list.Snippet.ChannelId); string desc = list.Snippet.Description; - playlist.Description = desc.Substring(0, Math.Min(desc.Length, 1024)) + (desc.Length > 1020 ? "..." : " "); - if (playlist.Description.Length < 2) - playlist.Description = "None"; - - try - { - playlist.Thumbnail = new Uri(list.Snippet.Thumbnails.Maxres.Url); - }catch (Exception ex) { } - playlist.AuthorName = channel.Snippet.Title; + playlist.Description = desc.Substring(0, Math.Min(desc.Length, 4092)) + (desc.Length > 4092 ? "..." : " "); + playlist.Thumbnail = new Uri(list.Snippet.Thumbnails.High.Url); playlist.CreationTime = (DateTime)list.Snippet.PublishedAt; playlist.YoutubeItem = list; - playlist.AuthorThumbnail = new Uri(channel.Snippet.Thumbnails.Default__.Url); - playlist.AuthorUri = new Uri($"https://www.youtube.com/channels/{channel.Id}"); + playlist.AuthorThumbnail = new Uri(channel.Snippet.Thumbnails.High.Url); + playlist.AuthorUri = new Uri($"https://www.youtube.com/playlist?list={playlist.Identifier}"); return playlist; } @@ -117,28 +101,21 @@ namespace TomatenMusic.Services return response.Items.First(); } - public async Task> GetRelatedVideosAsync(string id) + public async Task GetRelatedVideoAsync(string id) { var search = Service.Search.List("snippet"); search.RelatedToVideoId = id; search.Type = "video"; var response = await search.ExecuteAsync(); - return response.Items.Where(x => x.Snippet != null); + return response.Items.First(s => s.Snippet != null); } - public async Task GetRelatedTrackAsync(string id, List excludeIds) + public async Task GetRelatedTrackAsync(string id) { var audioService = TomatenMusicBot.ServiceProvider.GetRequiredService(); - var videos = await GetRelatedVideosAsync(id); - SearchResult video = null; - foreach (var vid in videos) - video = videos.First(x => !excludeIds.Contains(x.Id.VideoId)); - - if (video == null) - video = videos.FirstOrDefault(); - - var loadResult = new TomatenMusicTrack(await audioService.GetTrackAsync($"https://youtu.be/{video.Id.VideoId}")); + var video = await GetRelatedVideoAsync(id); + var loadResult = await audioService.GetTrackAsync($"https://youtu.be/{video.Id.VideoId}"); if (loadResult == null) throw new Exception("An Error occurred while processing the Request"); diff --git a/TomatenMusicCore/TomatenMusicBot.cs b/TomatenMusicCore/TomatenMusicBot.cs index a68e715..464ca2c 100644 --- a/TomatenMusicCore/TomatenMusicBot.cs +++ b/TomatenMusicCore/TomatenMusicBot.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging; using DSharpPlus; using DSharpPlus.EventArgs; using DSharpPlus.Entities; +using DSharpPlus.Net; using System.Linq; using DSharpPlus.SlashCommands; using DSharpPlus.SlashCommands.EventArgs; @@ -76,6 +77,7 @@ namespace TomatenMusic }) + // Lavalink .AddSingleton() .AddSingleton() .AddSingleton(new InactivityTrackingOptions @@ -87,9 +89,9 @@ namespace TomatenMusic .AddSingleton( new LavalinkNodeOptions { - RestUri = "http://127.0.0.1:2333", + RestUri = "http://116.202.92.16:2333", Password = config.LavaLinkPassword, - WebSocketUri = "ws://127.0.0.1:2333", + WebSocketUri = "ws://116.202.92.16:2333", AllowResuming = true }) @@ -99,8 +101,7 @@ namespace TomatenMusic .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton( - SpotifyClientConfig.CreateDefault().WithAuthenticator(new ClientCredentialsAuthenticator(config.SpotifyClientId, config.SpotifyClientSecret)))) + .AddSingleton(SpotifyClientConfig.CreateDefault().WithAuthenticator(new ClientCredentialsAuthenticator(config.SpotifyClientId, config.SpotifyClientSecret)))) .Build(); ServiceProvider = _host.Services; @@ -113,6 +114,7 @@ namespace TomatenMusic { await BuildServiceProvider(); + //_ = _host.StartAsync(); _host.Start(); var client = ServiceProvider.GetRequiredService(); @@ -124,14 +126,9 @@ namespace TomatenMusic { Services = ServiceProvider }); - - //slash.RegisterCommands(888493810554900491); - //slash.RegisterCommands(888493810554900491); - //slash.RegisterCommands(888493810554900491); - slash.RegisterCommands(); - slash.RegisterCommands(); - slash.RegisterCommands(); + slash.RegisterCommands(888493810554900491); + slash.RegisterCommands(888493810554900491); await client.StartAsync(); client.Ready += Client_Ready; @@ -146,13 +143,11 @@ namespace TomatenMusic private Task Client_Ready(DiscordClient sender, ReadyEventArgs e) { - var logger = ServiceProvider.GetRequiredService>(); var slash = sender.GetSlashCommands(); slash.SlashCommandInvoked += Slash_SlashCommandInvoked; slash.SlashCommandErrored += Slash_SlashCommandErrored; sender.UpdateStatusAsync(new DiscordActivity($"/ commands! Shard {sender.ShardId}", ActivityType.Watching)); - return Task.CompletedTask; } @@ -187,7 +182,7 @@ namespace TomatenMusic if (e.Exception is NotFoundException) logger.LogDebug($"{ ((NotFoundException)e.Exception).JsonMessage }"); if (e.Exception is BadRequestException) - logger.LogInformation($"{ ((BadRequestException)e.Exception).Errors }"); + logger.LogDebug($"{ ((BadRequestException)e.Exception).JsonMessage }"); return Task.CompletedTask; } diff --git a/TomatenMusicCore/TomatenMusicCore.csproj b/TomatenMusicCore/TomatenMusicCore.csproj index 36d5b2e..2a8bc65 100644 --- a/TomatenMusicCore/TomatenMusicCore.csproj +++ b/TomatenMusicCore/TomatenMusicCore.csproj @@ -1,23 +1,27 @@ - + net6.0 enable enable + + https://api.nuget.org/v3/index.json; + https://nuget.emzi0767.com/api/v3/index.json + - - - - + + + + - + - + diff --git a/TomatenMusicCore/Util/Common.cs b/TomatenMusicCore/Util/Common.cs index 478e9af..773b7a4 100644 --- a/TomatenMusicCore/Util/Common.cs +++ b/TomatenMusicCore/Util/Common.cs @@ -19,46 +19,32 @@ namespace TomatenMusic.Util { public static DiscordEmbed AsEmbed(LavalinkTrack track, LoopType loopType, int position = -1) - { - DiscordEmbedBuilder builder = new DiscordEmbedBuilder(AsEmbed(track, position)); - builder.AddField("Current Queue Loop", loopType.ToString(), true); - return builder; - } - - public static DiscordEmbed AsEmbed(LavalinkTrack track, int position = -1) { FullTrackContext context = (FullTrackContext)track.Context; DiscordEmbedBuilder builder = new DiscordEmbedBuilder() .WithTitle(track.Title) - .WithUrl(track.Source) - .WithDescription(context.YoutubeDescription) .AddField("Length", Common.GetTimestamp(track.Duration), true); - - if (context.YoutubeThumbnail != null) - builder.WithImageUrl(context.YoutubeThumbnail); - if (context.IsFile) { builder.WithAuthor(track.Author); - builder.WithUrl(track.Source); - } else builder .WithAuthor(track.Author, context.YoutubeAuthorUri.ToString(), context.YoutubeAuthorThumbnail.ToString()) - .WithUrl(track.Source); + .WithUrl(context.YoutubeUri) + .WithImageUrl(context.YoutubeThumbnail) + .WithDescription(context.YoutubeDescription); + + if (position != -1) { - builder.AddField("Queue Position", (position == 0 ? "Now Playing" : position.ToString()), true); + builder.AddField("Position", (position == 0 ? "Now Playing" : position.ToString()), true); } - + builder.AddField("Current Queue Loop", loopType.ToString(), true); if (!context.IsFile) { - if (track.Position.Seconds > 0) - builder.AddField("Starting Position", GetTimestamp(track.Position), true); - builder.AddField("Views", $"{context.YoutubeViews:N0} Views", true); builder.AddField("Rating", $"{context.YoutubeLikes:N0} 👍", true); builder.AddField("Upload Date", $"{context.YoutubeUploadDate.ToString("dd. MMMM, yyyy")}", true); @@ -69,7 +55,44 @@ namespace TomatenMusic.Util return builder; } - public static DiscordEmbed AsEmbed(ILavalinkPlaylist playlist) + public static DiscordEmbed AsEmbed(LavalinkTrack track, int position = -1) + { + FullTrackContext context = (FullTrackContext)track.Context; + + DiscordEmbedBuilder builder = new DiscordEmbedBuilder() + .WithTitle(track.Title) + .WithUrl(context.YoutubeUri) + .WithImageUrl(context.YoutubeThumbnail) + .WithDescription(context.YoutubeDescription) + .AddField("Length", Common.GetTimestamp(track.Duration), true); + + if (context.IsFile) + { + builder.WithAuthor(track.Author); + } + else + builder + .WithAuthor(track.Author, context.YoutubeAuthorUri.ToString(), context.YoutubeAuthorThumbnail.ToString()) + .WithUrl(context.YoutubeUri); + + if (position != -1) + { + builder.AddField("Position", (position == 0 ? "Now Playing" : position.ToString()), true); + } + + if (!context.IsFile) + { + builder.AddField("Views", $"{context.YoutubeViews:N0} Views", true); + builder.AddField("Rating", $"{context.YoutubeLikes:N0} 👍", true); + builder.AddField("Upload Date", $"{context.YoutubeUploadDate.ToString("dd. MMMM, yyyy")}", true); + builder.AddField("Comments", context.YoutubeCommentCount == null ? "Comments Disabled" : $"{context.YoutubeCommentCount:N0} Comments", true); + builder.AddField("Channel Subscriptions", $"{context.YoutubeAuthorSubs:N0} Subscribers", true); + } + + return builder; + } + + public static DiscordEmbed AsEmbed(LavalinkPlaylist playlist) { DiscordEmbedBuilder builder = new DiscordEmbedBuilder(); @@ -77,43 +100,39 @@ namespace TomatenMusic.Util if (playlist is YoutubePlaylist) { YoutubePlaylist youtubePlaylist = (YoutubePlaylist)playlist; - Console.WriteLine($"{playlist.AuthorName}, {playlist.AuthorUri.ToString()}, {playlist.AuthorThumbnail.ToString()}"); - builder.WithAuthor(playlist.AuthorName, playlist.AuthorUri.ToString(), youtubePlaylist.AuthorThumbnail.ToString()); - builder.WithTitle(playlist.Title); - builder.WithUrl(playlist.Url); - builder.WithDescription(TrackListString(playlist.Tracks, 4000)); - builder.WithImageUrl(youtubePlaylist.Thumbnail); - builder.AddField("Description", playlist.Description, false); - builder.AddField("Track Count", $"{playlist.Tracks.Count()} Tracks", true); - builder.AddField("Length", $"{Common.GetTimestamp(playlist.GetLength())}", true); - builder.AddField("Create Date", $"{youtubePlaylist.CreationTime:dd. MMMM, yyyy}", true); + builder + .WithAuthor(playlist.AuthorName, playlist.AuthorUri.ToString(), youtubePlaylist.AuthorThumbnail.ToString()) + .WithTitle(playlist.Name) + .WithUrl(playlist.Url) + .WithDescription(playlist.Description) + .WithImageUrl(youtubePlaylist.Thumbnail) + .AddField("Tracks", TrackListString(playlist.Tracks), false) + .AddField("Track Count", $"{playlist.Tracks.Count()} Tracks", true) + .AddField("Length", $"{Common.GetTimestamp(playlist.GetLength())}", true) + .AddField("Create Date", $"{youtubePlaylist.CreationTime:dd. MMMM, yyyy}", true); }else if (playlist is SpotifyPlaylist) { SpotifyPlaylist spotifyPlaylist = (SpotifyPlaylist)playlist; - - builder.WithTitle(playlist.Title); - builder.WithUrl(playlist.Url); - builder.WithDescription(TrackListString(playlist.Tracks, 4000)); - builder.AddField("Description", playlist.Description, false); - builder.AddField("Track Count", $"{playlist.Tracks.Count()} Tracks", true); - builder.AddField("Length", $"{Common.GetTimestamp(playlist.GetLength())}", true); - builder.AddField("Spotify Followers", $"{spotifyPlaylist.Followers:N0}", true); - if (spotifyPlaylist.AuthorThumbnail != null) - { - builder.WithAuthor(playlist.AuthorName, playlist.AuthorUri.ToString(), spotifyPlaylist.AuthorThumbnail.ToString()); - }else - builder.WithAuthor(playlist.AuthorName, playlist.AuthorUri.ToString()); + builder + .WithAuthor(playlist.AuthorName, playlist.AuthorUri.ToString(), spotifyPlaylist.AuthorThumbnail.ToString()) + .WithTitle(playlist.Name) + .WithUrl(playlist.Url) + .WithDescription(playlist.Description) + .AddField("Tracks", TrackListString(playlist.Tracks), false) + .AddField("Track Count", $"{playlist.Tracks.Count()} Tracks", true) + .AddField("Length", $"{Common.GetTimestamp(playlist.GetLength())}", true) + .AddField("Spotify Followers", $"{spotifyPlaylist.Followers:N0}", true); } - return builder.Build(); + return builder; } public static DiscordEmbed GetQueueEmbed(GuildPlayer player) { DiscordEmbedBuilder builder = new DiscordEmbedBuilder(); - builder.WithDescription(TrackListString(player.PlayerQueue.Queue, 4000)); + builder.WithDescription(TrackListString(player.PlayerQueue.Queue)); builder.WithTitle("Current Queue"); builder.WithAuthor($"{player.PlayerQueue.Queue.Count} Songs"); @@ -127,37 +146,29 @@ namespace TomatenMusic.Util builder.AddField("Length", GetTimestamp(timeSpan), true); builder.AddField("Loop Type", player.PlayerQueue.LoopType.ToString(), true); builder.AddField("Autoplay", player.Autoplay ? "✅" : "❌", true); - if (player.PlayerQueue.CurrentPlaylist != null) - builder.AddField("Current Playlist", $"[{player.PlayerQueue.CurrentPlaylist.Title}]({player.PlayerQueue.CurrentPlaylist.Url})", true); - if (player.PlayerQueue.PlayedTracks.Any()) - builder.AddField("History", TrackListString(player.PlayerQueue.PlayedTracks, 1000), true); + builder.AddField("History", TrackListString(player.PlayerQueue.PlayedTracks), true); + if (player.PlayerQueue.CurrentPlaylist != null) + builder.AddField("Current Playlist", $"[{player.PlayerQueue.CurrentPlaylist.Name}]({player.PlayerQueue.CurrentPlaylist.Url})", true); return builder; } - public static string TrackListString(IEnumerable tracks, int maxCharacters) + public static string TrackListString(IEnumerable tracks) { StringBuilder builder = new StringBuilder(); - string lastString = " "; int count = 1; foreach (LavalinkTrack track in tracks) { - if (builder.ToString().Length > maxCharacters) + FullTrackContext context = (FullTrackContext)track.Context; + if (count > 15) { - builder = new StringBuilder(lastString); - builder.Append(String.Format("***And {0} more...***", tracks.Count() - count)); + builder.Append(String.Format("***And {0} more...***", tracks.Count() - 15)); break; } - FullTrackContext context = (FullTrackContext)track.Context; - - lastString = builder.ToString(); - builder.Append(count).Append(": ").Append($"[{track.Title}]({track.Source})").Append(" [").Append(Common.GetTimestamp(track.Duration)).Append("] | "); - builder.Append($"[{track.Author}]({context.YoutubeAuthorUri})"); - if (track.Position.Seconds != 0) - builder.Append($" | 🕑"); - builder.Append("\n\n"); + builder.Append(count).Append(": ").Append($"[{track.Title}]({context.YoutubeUri})").Append(" [").Append(Common.GetTimestamp(track.Duration)).Append("] | "); + builder.Append($"[{track.Author}]({context.YoutubeAuthorUri})").Append("\n\n"); count++; } builder.Append(" "); @@ -236,29 +247,19 @@ namespace TomatenMusic.Util DiscordEmbedBuilder builder = new DiscordEmbedBuilder(); LavalinkTrack track = player.CurrentTrack; - if (track == null) - { - builder.WithColor(DiscordColor.Red); - builder.WithTitle("Nothing Playing"); - builder.WithImageUrl("https://media.tomatentum.net/TMBanner.gif"); - return builder; - } - FullTrackContext context = (FullTrackContext)track.Context; string progressBar = $"|{ProgressBar((int)player.Position.Position.TotalSeconds, (int)track.Duration.TotalSeconds)}|\n [{Common.GetTimestamp(player.Position.Position)}/{Common.GetTimestamp(track.Duration)}]"; - - builder.WithAuthor(track.Author); + + builder.WithAuthor(track.Author, context.YoutubeAuthorUri.ToString(), context.YoutubeAuthorThumbnail.ToString()); builder.WithTitle(track.Title); - builder.WithUrl(track.Source); - builder.WithColor(player.State == PlayerState.Paused ? DiscordColor.Orange : DiscordColor.Green); + builder.WithUrl(context.YoutubeUri); + builder.WithImageUrl(context.YoutubeThumbnail); builder.AddField("Length", Common.GetTimestamp(track.Duration), true); builder.AddField("Loop", player.PlayerQueue.LoopType.ToString(), true); builder.AddField("Progress", progressBar, true); if (!context.IsFile) { - builder.WithAuthor(track.Author, context.YoutubeAuthorUri.ToString(), context.YoutubeAuthorThumbnail.ToString()); - builder.WithImageUrl(context.YoutubeThumbnail); builder.AddField("Views", $"{context.YoutubeViews:N0} Views", true); builder.AddField("Rating", $"{context.YoutubeLikes:N0} 👍", true); builder.AddField("Upload Date", $"{context.YoutubeUploadDate.ToString("dd. MMMM, yyyy")}", true);