- Re-added .qap / .queueautoplay

- Several strings and commands related to music have been changed
  - Changed .ms / .movesong to .tm / .trackmove but kept old aliases
  - Changed ~~song~~ -> 	rack throughout music module strings
- Updated CHANGELOG.md
This commit is contained in:
Kwoth
2022-02-13 15:49:48 +01:00
parent 6895c8a2a4
commit 7ed1b13e85
20 changed files with 3054 additions and 181 deletions

View File

@@ -103,7 +103,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
var (trackInfo, index) = await mp.TryEnqueueTrackAsync(query, ctx.User.ToString(), asNext, forcePlatform);
if (trackInfo is null)
{
await ReplyErrorLocalizedAsync(strs.song_not_found);
await ReplyErrorLocalizedAsync(strs.track_not_found);
return;
}
@@ -111,7 +111,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
{
var embed = _eb.Create()
.WithOkColor()
.WithAuthor(GetText(strs.queued_song) + " #" + (index + 1), MUSIC_ICON_URL)
.WithAuthor(GetText(strs.queued_track) + " #" + (index + 1), MUSIC_ICON_URL)
.WithDescription($"{trackInfo.PrettyName()}\n{GetText(strs.queue)} ")
.WithFooter(trackInfo.Platform.ToString());
@@ -248,7 +248,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
[RequireContext(ContextType.Guild)]
public async partial Task ListQueue()
{
// show page with the current song
// show page with the current track
if (!_service.TryGetMusicPlayer(ctx.Guild.Id, out var mp))
{
await ReplyErrorLocalizedAsync(strs.no_player);
@@ -291,8 +291,8 @@ public sealed partial class Music : NadekoModule<IMusicService>
add += "🔂 " + GetText(strs.repeating_track) + "\n";
else
{
// if (mp.Autoplay)
// add += "↪ " + GetText(strs.autoplaying) + "\n";
if (mp.AutoPlay)
add += "↪ " + GetText(strs.autoplaying) + "\n";
// if (mp.FairPlay && !mp.Autoplay)
// add += " " + GetText(strs.fairplay) + "\n";
if (repeatType == PlayerRepeatType.Queue)
@@ -339,7 +339,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
if (videos.Count == 0)
{
await ReplyErrorLocalizedAsync(strs.song_not_found);
await ReplyErrorLocalizedAsync(strs.track_not_found);
return;
}
@@ -388,7 +388,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
{
if (index < 1)
{
await ReplyErrorLocalizedAsync(strs.removed_song_error);
await ReplyErrorLocalizedAsync(strs.removed_track_error);
return;
}
@@ -402,16 +402,16 @@ public sealed partial class Music : NadekoModule<IMusicService>
return;
}
if (!mp.TryRemoveTrackAt(index - 1, out var song))
if (!mp.TryRemoveTrackAt(index - 1, out var track))
{
await ReplyErrorLocalizedAsync(strs.removed_song_error);
await ReplyErrorLocalizedAsync(strs.removed_track_error);
return;
}
var embed = _eb.Create()
.WithAuthor(GetText(strs.removed_song) + " #" + index, MUSIC_ICON_URL)
.WithDescription(song.PrettyName())
.WithFooter(song.PrettyInfo())
.WithAuthor(GetText(strs.removed_track) + " #" + index, MUSIC_ICON_URL)
.WithDescription(track.PrettyName())
.WithFooter(track.PrettyInfo())
.WithErrorColor();
await _service.SendToOutputAsync(ctx.Guild.Id, embed);
@@ -550,7 +550,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
[Cmd]
[RequireContext(ContextType.Guild)]
public async partial Task MoveSong(int from, int to)
public async partial Task TrackMove(int from, int to)
{
if (--from < 0 || --to < 0 || from == to)
{
@@ -578,7 +578,7 @@ public sealed partial class Music : NadekoModule<IMusicService>
var embed = _eb.Create()
.WithTitle(track.Title.TrimTo(65))
.WithAuthor(GetText(strs.song_moved), MUSIC_ICON_URL)
.WithAuthor(GetText(strs.track_moved), MUSIC_ICON_URL)
.AddField(GetText(strs.from_position), $"#{from + 1}", true)
.AddField(GetText(strs.to_position), $"#{to + 1}", true)
.WithOkColor();
@@ -744,4 +744,15 @@ public sealed partial class Music : NadekoModule<IMusicService>
await _service.SetMusicQualityAsync(ctx.Guild.Id, preset);
await ReplyConfirmLocalizedAsync(strs.music_quality_set(Format.Bold(preset.ToString())));
}
[Cmd]
[RequireContext(ContextType.Guild)]
public async partial Task QueueAutoPlay()
{
var newValue = await _service.ToggleQueueAutoPlayAsync(ctx.Guild.Id);
if (newValue)
await ReplyConfirmLocalizedAsync(strs.music_autoplay_on);
else
await ReplyConfirmLocalizedAsync(strs.music_autoplay_off);
}
}

View File

@@ -32,4 +32,5 @@ public interface IMusicService : IPlaceholderProvider
Task<bool> ToggleAutoDisconnectAsync(ulong guildId);
Task<QualityPreset> GetMusicQualityAsync(ulong guildId);
Task SetMusicQualityAsync(ulong guildId, QualityPreset preset);
Task<bool> ToggleQueueAutoPlayAsync(ulong guildId);
}

View File

@@ -156,7 +156,12 @@ public sealed class MusicService : IMusicService
_outputChannels[guildId] = (defaultChannel, overrideChannel);
var mp = new MusicPlayer(queue, resolver, proxy, settings.QualityPreset);
var mp = new MusicPlayer(queue,
resolver,
proxy,
_googleApiService,
settings.QualityPreset,
settings.AutoPlay);
mp.SetRepeat(settings.PlayerRepeat);
@@ -191,7 +196,7 @@ public sealed class MusicService : IMusicService
_ = lastFinishedMessage?.DeleteAsync();
var embed = _eb.Create()
.WithOkColor()
.WithAuthor(GetText(guildId, strs.finished_song), Music.MUSIC_ICON_URL)
.WithAuthor(GetText(guildId, strs.finished_track), Music.MUSIC_ICON_URL)
.WithDescription(trackInfo.PrettyName())
.WithFooter(trackInfo.PrettyTotalTime());
@@ -207,7 +212,7 @@ public sealed class MusicService : IMusicService
_ = lastPlayingMessage?.DeleteAsync();
var embed = _eb.Create()
.WithOkColor()
.WithAuthor(GetText(guildId, strs.playing_song(index + 1)), Music.MUSIC_ICON_URL)
.WithAuthor(GetText(guildId, strs.playing_track(index + 1)), Music.MUSIC_ICON_URL)
.WithDescription(trackInfo.PrettyName())
.WithFooter($"{mp.PrettyVolume()} | {trackInfo.PrettyInfo()}");
@@ -288,7 +293,7 @@ public sealed class MusicService : IMusicService
public IEnumerable<(string Name, Func<string> Func)> GetPlaceholders()
{
// random song that's playing
// random track that's playing
yield return ("%music.playing%", () =>
{
var randomPlayingTrack = _players.Select(x => x.Value.GetCurrentTrack(out _))
@@ -438,5 +443,17 @@ public sealed class MusicService : IMusicService
},
preset);
public async Task<bool> ToggleQueueAutoPlayAsync(ulong guildId)
{
var newValue = false;
await ModifySettingsInternalAsync(guildId,
(settings, _) => newValue = settings.AutoPlay = !settings.AutoPlay,
false);
if (TryGetMusicPlayer(guildId, out var mp))
mp.AutoPlay = newValue;
return newValue;
}
#endregion
}

View File

@@ -10,6 +10,7 @@ public interface IMusicPlayer : IDisposable
bool IsKilled { get; }
int CurrentIndex { get; }
public PlayerRepeatType Repeat { get; }
bool AutoPlay { get; set; }
void Stop();
void Clear();

View File

@@ -2,6 +2,7 @@
public interface ITrackInfo
{
public string Id => string.Empty;
public string Title { get; }
public string Url { get; }
public string Thumbnail { get; }

View File

@@ -28,6 +28,7 @@ public sealed class MusicPlayer : IMusicPlayer
private readonly IMusicQueue _queue;
private readonly ITrackResolveProvider _trackResolveProvider;
private readonly IVoiceProxy _proxy;
private readonly IGoogleApiService _googleApiService;
private readonly ISongBuffer _songBuffer;
private bool skipped;
@@ -35,15 +36,21 @@ public sealed class MusicPlayer : IMusicPlayer
private readonly Thread _thread;
private readonly Random _rng;
public bool AutoPlay { get; set; }
public MusicPlayer(
IMusicQueue queue,
ITrackResolveProvider trackResolveProvider,
IVoiceProxy proxy,
QualityPreset qualityPreset)
IGoogleApiService googleApiService,
QualityPreset qualityPreset,
bool autoPlay)
{
_queue = queue;
_trackResolveProvider = trackResolveProvider;
_proxy = proxy;
_googleApiService = googleApiService;
AutoPlay = autoPlay;
_rng = new NadekoRandom();
_vc = GetVoiceClient(qualityPreset);
@@ -265,7 +272,29 @@ public sealed class MusicPlayer : IMusicPlayer
{
cancellationTokenSource.Cancel();
// turn off green in vc
_ = OnCompleted?.Invoke(this, track);
// todo update when settings are changed
if (AutoPlay && track.Platform == MusicPlatform.Youtube)
{
try
{
var relatedSongs = await _googleApiService.GetRelatedVideosAsync(track.TrackInfo.Id, 5);
var related = relatedSongs.Shuffle().FirstOrDefault();
if (related is not null)
{
var relatedTrack = await _trackResolveProvider.QuerySongAsync(related, MusicPlatform.Youtube);
if (relatedTrack is not null)
EnqueueTrack(relatedTrack, "Autoplay");
}
}
catch (Exception ex)
{
Log.Warning(ex, "Failed queueing a related song via autoplay");
}
}
HandleQueuePostTrack();
skipped = false;

View File

@@ -1,30 +1,15 @@
namespace NadekoBot.Modules.Music;
public sealed class RemoteTrackInfo : ITrackInfo
public sealed record RemoteTrackInfo(
string Id,
string Title,
string Url,
string Thumbnail,
TimeSpan Duration,
MusicPlatform Platform,
Func<Task<string?>> _streamFactory) : ITrackInfo
{
public string Title { get; }
public string Url { get; }
public string Thumbnail { get; }
public TimeSpan Duration { get; }
public MusicPlatform Platform { get; }
private readonly Func<Task<string?>> _streamFactory;
public RemoteTrackInfo(
string title,
string url,
string thumbnail,
TimeSpan duration,
MusicPlatform platform,
Func<Task<string?>> streamFactory)
{
_streamFactory = streamFactory;
Title = title;
Url = url;
Thumbnail = thumbnail;
Duration = duration;
Platform = platform;
}
private readonly Func<Task<string?>> _streamFactory = _streamFactory;
public async ValueTask<string?> GetStreamUrl()
=> await _streamFactory();

View File

@@ -94,7 +94,9 @@ public sealed class YtdlYoutubeResolver : IYoutubeResolver
}
private ITrackInfo DataToInfo(in YtTrackData trackData)
=> new RemoteTrackInfo(trackData.Title,
=> new RemoteTrackInfo(
trackData.Id,
trackData.Title,
$"https://youtube.com/watch?v={trackData.Id}",
trackData.Thumbnail,
trackData.Duration,