diff --git a/samples/Lavalink4NET.DSharpPlus.ExampleBot/Lavalink4NET.DSharpPlus.ExampleBot.csproj b/samples/Lavalink4NET.DSharpPlus.ExampleBot/Lavalink4NET.DSharpPlus.ExampleBot.csproj index f9d43dfe..aad59a8f 100644 --- a/samples/Lavalink4NET.DSharpPlus.ExampleBot/Lavalink4NET.DSharpPlus.ExampleBot.csproj +++ b/samples/Lavalink4NET.DSharpPlus.ExampleBot/Lavalink4NET.DSharpPlus.ExampleBot.csproj @@ -1,19 +1,21 @@  - - Exe - net7.0 - enable - + + Exe + net7.0 + enable + ExampleBot + - - - - - - + + + + + + + - - - + + + \ No newline at end of file diff --git a/samples/Lavalink4NET.DSharpPlus.ExampleBot/MusicCommands.cs b/samples/Lavalink4NET.DSharpPlus.ExampleBot/MusicCommands.cs new file mode 100644 index 00000000..56077357 --- /dev/null +++ b/samples/Lavalink4NET.DSharpPlus.ExampleBot/MusicCommands.cs @@ -0,0 +1,106 @@ +namespace ExampleBot; + +using System; +using System.Threading.Tasks; +using DSharpPlus.Entities; +using DSharpPlus.SlashCommands; +using Lavalink4NET; +using Lavalink4NET.Players; +using Lavalink4NET.Players.Queued; +using Lavalink4NET.Rest.Entities.Tracks; +using Microsoft.Extensions.Options; + +public class MusicCommands : ApplicationCommandModule +{ + private readonly IAudioService _audioService; + + public MusicCommands(IAudioService audioService) + { + ArgumentNullException.ThrowIfNull(audioService); + + _audioService = audioService; + } + + [SlashCommand("play", description: "Plays music")] + public async Task Play(InteractionContext interactionContext, [Option("query", "Track to play")] string query) + { + await interactionContext.DeferAsync().ConfigureAwait(false); + + var player = await GetPlayerAsync(interactionContext, connectToVoiceChannel: true).ConfigureAwait(false); + + if (player is null) + { + return; + } + + var track = await _audioService.Tracks + .LoadTrackAsync(query, TrackSearchMode.YouTube) + .ConfigureAwait(false); + + if (track is null) + { + var errorResponse = new DiscordFollowupMessageBuilder() + .WithContent("😖 No results.") + .AsEphemeral(); + + await interactionContext + .FollowUpAsync(errorResponse) + .ConfigureAwait(false); + + return; + } + + var position = await player + .PlayAsync(track) + .ConfigureAwait(false); + + if (position is 0) + { + await interactionContext + .FollowUpAsync(new DiscordFollowupMessageBuilder().WithContent($"🔈 Playing: {track.Uri}")) + .ConfigureAwait(false); + } + else + { + await interactionContext + .FollowUpAsync(new DiscordFollowupMessageBuilder().WithContent($"🔈 Added to queue: {track.Uri}")) + .ConfigureAwait(false); + } + } + + private async ValueTask GetPlayerAsync(InteractionContext interactionContext, bool connectToVoiceChannel = true) + { + ArgumentNullException.ThrowIfNull(interactionContext); + + var retrieveOptions = new PlayerRetrieveOptions( + ChannelBehavior: connectToVoiceChannel ? PlayerChannelBehavior.Join : PlayerChannelBehavior.None); + + var playerOptions = new QueuedLavalinkPlayerOptions { HistoryCapacity = 10000 }; + + var result = await _audioService.Players + .RetrieveAsync(interactionContext.Guild.Id, interactionContext.Member?.VoiceState.Channel.Id, playerFactory: PlayerFactory.Queued, Options.Create(playerOptions), retrieveOptions) + .ConfigureAwait(false); + + if (!result.IsSuccess) + { + var errorMessage = result.Status switch + { + PlayerRetrieveStatus.UserNotInVoiceChannel => "You are not connected to a voice channel.", + PlayerRetrieveStatus.BotNotConnected => "The bot is currently not connected.", + _ => "Unknown error.", + }; + + var errorResponse = new DiscordFollowupMessageBuilder() + .WithContent(errorMessage) + .AsEphemeral(); + + await interactionContext + .FollowUpAsync(errorResponse) + .ConfigureAwait(false); + + return null; + } + + return result.Player; + } +} \ No newline at end of file diff --git a/samples/Lavalink4NET.DSharpPlus.ExampleBot/Program.cs b/samples/Lavalink4NET.DSharpPlus.ExampleBot/Program.cs index 8acf69f3..b6d859a1 100644 --- a/samples/Lavalink4NET.DSharpPlus.ExampleBot/Program.cs +++ b/samples/Lavalink4NET.DSharpPlus.ExampleBot/Program.cs @@ -2,10 +2,10 @@ using System.Threading; using System.Threading.Tasks; using DSharpPlus; -using Lavalink4NET; +using DSharpPlus.EventArgs; +using DSharpPlus.SlashCommands; +using ExampleBot; using Lavalink4NET.Extensions; -using Lavalink4NET.Players; -using Lavalink4NET.Players.Queued; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -17,7 +17,6 @@ builder.Services.AddSingleton(); builder.Services.AddSingleton(new DiscordConfiguration { Token = "", }); // Put token here -// Lavalink builder.Services.AddLavalink(); // Logging @@ -27,36 +26,43 @@ file sealed class ApplicationHost : BackgroundService { + private readonly IServiceProvider _serviceProvider; private readonly DiscordClient _discordClient; - private readonly IAudioService _audioService; - public ApplicationHost(DiscordClient discordClient, IAudioService audioService) + public ApplicationHost(IServiceProvider serviceProvider, DiscordClient discordClient) { + ArgumentNullException.ThrowIfNull(serviceProvider); ArgumentNullException.ThrowIfNull(discordClient); - ArgumentNullException.ThrowIfNull(audioService); + _serviceProvider = serviceProvider; _discordClient = discordClient; - _audioService = audioService; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { + _discordClient + .UseSlashCommands(new SlashCommandsConfiguration { Services = _serviceProvider }) + .RegisterCommands(0); // Add guild id here + // connect to discord gateway and initialize node connection await _discordClient .ConnectAsync() .ConfigureAwait(false); - await _audioService - .WaitForReadyAsync(stoppingToken) - .ConfigureAwait(false); + var readyTaskCompletionSource = new TaskCompletionSource(); - var playerOptions = new LavalinkPlayerOptions + Task SetResult(DiscordClient client, ReadyEventArgs eventArgs) { - InitialTrack = new TrackQueueItem("https://www.youtube.com/watch?v=dQw4w9WgXcQ"), - }; + readyTaskCompletionSource.TrySetResult(); + return Task.CompletedTask; + } + + _discordClient.Ready += SetResult; + await readyTaskCompletionSource.Task.ConfigureAwait(false); + _discordClient.Ready -= SetResult; - await _audioService.Players - .JoinAsync(0, 0, playerOptions, stoppingToken) // Ids + await Task + .Delay(Timeout.InfiniteTimeSpan, stoppingToken) .ConfigureAwait(false); } } \ No newline at end of file