194 lines
6.1 KiB
C#
194 lines
6.1 KiB
C#
using System.ComponentModel;
|
|
using System.Text;
|
|
using Cassette.Extensions;
|
|
using JetBrains.Annotations;
|
|
using Lavalink4NET;
|
|
using Lavalink4NET.Rest.Entities.Tracks;
|
|
using Remora.Commands.Attributes;
|
|
using Remora.Commands.Groups;
|
|
using Remora.Discord.API.Abstractions.Objects;
|
|
using Remora.Discord.Commands.Attributes;
|
|
using Remora.Discord.Commands.Conditions;
|
|
using Remora.Discord.Commands.Contexts;
|
|
using Remora.Discord.Commands.Feedback.Services;
|
|
using Remora.Results;
|
|
|
|
namespace Cassette.Commands;
|
|
|
|
/// <summary>
|
|
/// A <see cref="CommandGroup"/> that controls the music player.
|
|
/// </summary>
|
|
public sealed class ControlsCommandGroup(
|
|
ICommandContext commandContext,
|
|
IAudioService audioService,
|
|
FeedbackService feedbackService) : CommandGroup
|
|
{
|
|
[Command("play")]
|
|
[Description("Plays or adds the requested track to the queue")]
|
|
[RequireBotDiscordPermissions(DiscordPermission.Connect)]
|
|
[DiscordDefaultDMPermission(false)]
|
|
[UsedImplicitly]
|
|
public async Task<Result> PlayCommandAsync(
|
|
[Description("URL or YouTube query")] string query)
|
|
{
|
|
var player = await LavalinkPlayer.GetPlayerAsync(commandContext, audioService, feedbackService, true);
|
|
if (player is null)
|
|
{
|
|
return Result.FromSuccess();
|
|
}
|
|
|
|
var track = await audioService.Tracks.LoadTrackAsync(query, TrackSearchMode.YouTube);
|
|
if (track is null)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"Not found.", feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
await player.PlayAsync(track);
|
|
|
|
var message = new StringBuilder().Append($"Added {track.Display()}");
|
|
|
|
if (player.Queue.IsEmpty)
|
|
{
|
|
message.Append(" to begin playing");
|
|
}
|
|
|
|
if (!player.Queue.IsEmpty)
|
|
{
|
|
message.Append(" to the queue at position ").Append(player.Queue.Count);
|
|
}
|
|
|
|
return await feedbackService.SendContextualMessageResult(
|
|
message.ToString(), feedbackService.Theme.Success);
|
|
}
|
|
|
|
[Command("pause")]
|
|
[Description("Pauses the current track")]
|
|
[DiscordDefaultDMPermission(false)]
|
|
[UsedImplicitly]
|
|
public async Task<Result> PauseCommandAsync()
|
|
{
|
|
var player = await LavalinkPlayer.GetPlayerAsync(
|
|
commandContext, audioService, feedbackService);
|
|
if (player is null)
|
|
{
|
|
return Result.FromSuccess();
|
|
}
|
|
|
|
if (player.CurrentTrack is null)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"There's nothing playing right now.",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
if (player.IsPaused)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"Player is currently paused",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
await player.PauseAsync();
|
|
|
|
return await feedbackService.SendContextualMessageResult(
|
|
$"Paused {player.CurrentTrack.Display()}", feedbackService.Theme.Success);
|
|
}
|
|
|
|
[Command("resume")]
|
|
[Description("Resumes the current track")]
|
|
[DiscordDefaultDMPermission(false)]
|
|
[UsedImplicitly]
|
|
public async Task<Result> ResumeCommandAsync()
|
|
{
|
|
var player = await LavalinkPlayer.GetPlayerAsync(
|
|
commandContext, audioService, feedbackService);
|
|
if (player is null)
|
|
{
|
|
return Result.FromSuccess();
|
|
}
|
|
|
|
if (player.CurrentTrack is null)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"There's nothing playing right now.",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
if (!player.IsPaused)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"Player is currently not paused.",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
await player.ResumeAsync();
|
|
|
|
return await feedbackService.SendContextualMessageResult(
|
|
$"Resumed {player.CurrentTrack.Display()}", feedbackService.Theme.Success);
|
|
}
|
|
|
|
[Command("seek")]
|
|
[Description("Rewinds the current track to a specific position")]
|
|
[DiscordDefaultDMPermission(false)]
|
|
[UsedImplicitly]
|
|
public async Task<Result> SeekCommandAsync(
|
|
[Description("Position to rewind")] TimeSpan position)
|
|
{
|
|
var player = await LavalinkPlayer.GetPlayerAsync(
|
|
commandContext, audioService, feedbackService);
|
|
if (player is null)
|
|
{
|
|
return Result.FromSuccess();
|
|
}
|
|
|
|
if (player.CurrentTrack is null)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"There's nothing playing right now.",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
if (player.CurrentTrack is null)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"There's nothing playing right now.",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
var track = player.CurrentTrack;
|
|
|
|
await player.SeekAsync(position);
|
|
|
|
return await feedbackService.SendContextualMessageResult(
|
|
$"{track.Display()} rewound to {position.ReadableDuration()}", feedbackService.Theme.Success);
|
|
}
|
|
|
|
[Command("skip")]
|
|
[Description("Skips the current track")]
|
|
[DiscordDefaultDMPermission(false)]
|
|
[UsedImplicitly]
|
|
public async Task<Result> SkipCommandAsync()
|
|
{
|
|
var player = await LavalinkPlayer.GetPlayerAsync(
|
|
commandContext, audioService, feedbackService);
|
|
if (player is null)
|
|
{
|
|
return Result.FromSuccess();
|
|
}
|
|
|
|
if (player.CurrentTrack is null)
|
|
{
|
|
return await feedbackService.SendContextualMessageResult(
|
|
"There's nothing playing right now.",
|
|
feedbackService.Theme.FaultOrDanger);
|
|
}
|
|
|
|
var track = player.CurrentTrack;
|
|
|
|
await player.SkipAsync();
|
|
|
|
return await feedbackService.SendContextualMessageResult(
|
|
$"Skipped {track.Display()}", feedbackService.Theme.Success);
|
|
}
|
|
}
|