diff --git a/NadekoBot/Modules/Music/Classes/MusicControls.cs b/NadekoBot/Modules/Music/Classes/MusicControls.cs index afe724b6..2aba6075 100644 --- a/NadekoBot/Modules/Music/Classes/MusicControls.cs +++ b/NadekoBot/Modules/Music/Classes/MusicControls.cs @@ -51,6 +51,7 @@ namespace NadekoBot.Modules.Music.Classes public bool RepeatSong { get; private set; } = false; public bool RepeatPlaylist { get; private set; } = false; public bool Autoplay { get; set; } = false; + public uint MaxQueueSize { get; set; } = 0; public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume) { @@ -172,6 +173,7 @@ namespace NadekoBot.Modules.Music.Classes { if (s == null) throw new ArgumentNullException(nameof(s)); + ThrowIfQueueFull(); lock (playlistLock) { s.MusicPlayer = this; @@ -244,5 +246,13 @@ namespace NadekoBot.Modules.Music.Classes internal bool ToggleRepeatPlaylist() => this.RepeatPlaylist = !this.RepeatPlaylist; internal bool ToggleAutoplay() => this.Autoplay = !this.Autoplay; + + internal void ThrowIfQueueFull() + { + if (MaxQueueSize == 0) + return; + if (playlist.Count >= MaxQueueSize) + throw new PlaylistFullException(); + } } } diff --git a/NadekoBot/Modules/Music/Classes/PlaylistFullException.cs b/NadekoBot/Modules/Music/Classes/PlaylistFullException.cs new file mode 100644 index 00000000..15541d42 --- /dev/null +++ b/NadekoBot/Modules/Music/Classes/PlaylistFullException.cs @@ -0,0 +1,12 @@ +using System; + +namespace NadekoBot.Modules.Music.Classes +{ + class PlaylistFullException : Exception + { + public PlaylistFullException(string message) : base(message) + { + } + public PlaylistFullException() : base("Queue is full.") { } + } +} diff --git a/NadekoBot/Modules/Music/MusicModule.cs b/NadekoBot/Modules/Music/MusicModule.cs index e1aae9b4..70444a80 100644 --- a/NadekoBot/Modules/Music/MusicModule.cs +++ b/NadekoBot/Modules/Music/MusicModule.cs @@ -230,7 +230,7 @@ namespace NadekoBot.Modules.Music }); cgb.CreateCommand("max") - .Description("Sets the music volume to 100% (real max is actually 150%).\n**Usage**: `!m max`") + .Description("Sets the music volume to 100%.\n**Usage**: `!m max`") .Do(e => { MusicPlayer musicPlayer; @@ -296,7 +296,7 @@ namespace NadekoBot.Modules.Music var ids = await SearchHelper.GetVideoIDs(plId, 500).ConfigureAwait(false); if (ids == null || ids.Count == 0) { - await e.Channel.SendMessage($"🎵`Failed to find any songs.`"); + await e.Channel.SendMessage($"🎵 `Failed to find any songs.`"); return; } //todo TEMPORARY SOLUTION, USE RESOLVE QUEUE IN THE FUTURE @@ -310,6 +310,8 @@ namespace NadekoBot.Modules.Music { await QueueSong(e.User, e.Channel, e.User.VoiceChannel, id, true).ConfigureAwait(false); } + catch (PlaylistFullException) + { break; } catch { } } await msg.Edit("🎵 `Playlist queue complete.`").ConfigureAwait(false); @@ -335,14 +337,18 @@ namespace NadekoBot.Modules.Music foreach (var svideo in scvids.Skip(1)) { - mp.AddSong(new Song(new Classes.SongInfo + try { - Title = svideo.FullName, - Provider = "SoundCloud", - Uri = svideo.StreamLink, - ProviderType = MusicType.Normal, - Query = svideo.TrackLink, - }), e.User.Name); + mp.AddSong(new Song(new Classes.SongInfo + { + Title = svideo.FullName, + Provider = "SoundCloud", + Uri = svideo.StreamLink, + ProviderType = MusicType.Normal, + Query = svideo.TrackLink, + }), e.User.Name); + } + catch (PlaylistFullException) { break; } } }); @@ -362,7 +368,15 @@ namespace NadekoBot.Modules.Music .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System)); foreach (var file in fileEnum) { - await QueueSong(e.User, e.Channel, e.User.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); + try + { + await QueueSong(e.User, e.Channel, e.User.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); + } + catch (PlaylistFullException) + { + break; + } + catch { } } await e.Channel.SendMessage("🎵 `Directory queue complete.`").ConfigureAwait(false); } @@ -481,6 +495,29 @@ namespace NadekoBot.Modules.Music }); + cgb.CreateCommand("setmaxqueue") + .Alias("smq") + .Description($"Sets a maximum queue size. Supply 0 or no argument to have no limit. \n**Usage**: `{Prefix} smq` 50 or `{Prefix} smq`") + .Parameter("size", ParameterType.Unparsed) + .Do(async e => + { + MusicPlayer musicPlayer; + if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) + { + return; + } + + var sizeStr = e.GetArg("size")?.Trim(); + uint size = 0; + if (string.IsNullOrWhiteSpace(sizeStr) || !uint.TryParse(sizeStr, out size)) + { + size = 0; + } + + musicPlayer.MaxQueueSize = size; + await e.Channel.SendMessage($"🎵 `Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}`"); + }); + cgb.CreateCommand("cleanup") .Description("Cleans up hanging voice connections. **Bot Owner Only!**\n**Usage**: `!m cleanup`") .AddCheck(SimpleCheckers.OwnerOnly()) @@ -630,6 +667,10 @@ namespace NadekoBot.Modules.Music { await QueueSong(e.User, textCh, voiceCh, si.Query, true, (MusicType)si.ProviderType).ConfigureAwait(false); } + catch (PlaylistFullException) + { + break; + } catch (Exception ex) { Console.WriteLine($"Failed QueueSong in load playlist. {ex}"); @@ -800,8 +841,19 @@ namespace NadekoBot.Modules.Music }; return mp; }); - var resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false); - musicPlayer.AddSong(resolvedSong, queuer.Name); + Song resolvedSong; + try + { + musicPlayer.ThrowIfQueueFull(); + resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false); + + musicPlayer.AddSong(resolvedSong, queuer.Name); + } + catch (PlaylistFullException) + { + await textCh.SendMessage($"🎵 `Queue is full at {musicPlayer.MaxQueueSize}/{musicPlayer.MaxQueueSize}.` "); + throw; + } if (!silent) { var queuedMessage = await textCh.SendMessage($"🎵`Queued`{resolvedSong.PrettyName} **at** `#{musicPlayer.Playlist.Count}`").ConfigureAwait(false); diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index 84efa690..09bc70ea 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -144,6 +144,7 @@ +