Shuffle will now show in .lq at the top, and instead of shuffling playlist, it will randomly jump to a song in the playlist. "
This commit is contained in:
		@@ -1,18 +1,14 @@
 | 
				
			|||||||
using Discord.Commands;
 | 
					using Discord.Commands;
 | 
				
			||||||
using Discord.WebSocket;
 | 
					using Discord.WebSocket;
 | 
				
			||||||
using NadekoBot.Services;
 | 
					using NadekoBot.Services;
 | 
				
			||||||
using System.IO;
 | 
					 | 
				
			||||||
using Discord;
 | 
					using Discord;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
using NadekoBot.Attributes;
 | 
					using NadekoBot.Attributes;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using NadekoBot.Extensions;
 | 
					using NadekoBot.Extensions;
 | 
				
			||||||
using System.Net.Http;
 | 
					 | 
				
			||||||
using Newtonsoft.Json.Linq;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using NadekoBot.Services.Database.Models;
 | 
					using NadekoBot.Services.Database.Models;
 | 
				
			||||||
using System.Threading;
 | 
					 | 
				
			||||||
using NadekoBot.Services.Music;
 | 
					using NadekoBot.Services.Music;
 | 
				
			||||||
using NadekoBot.DataStructures;
 | 
					using NadekoBot.DataStructures;
 | 
				
			||||||
using System.Collections.Concurrent;
 | 
					using System.Collections.Concurrent;
 | 
				
			||||||
@@ -102,24 +98,26 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
                                                                .WithThumbnailUrl(songInfo.Thumbnail)
 | 
					                                                                .WithThumbnailUrl(songInfo.Thumbnail)
 | 
				
			||||||
                                                                .WithFooter(ef => ef.WithText(songInfo.PrettyProvider)))
 | 
					                                                                .WithFooter(ef => ef.WithText(songInfo.PrettyProvider)))
 | 
				
			||||||
                                                                .ConfigureAwait(false);
 | 
					                                                                .ConfigureAwait(false);
 | 
				
			||||||
 | 
					                        if (mp.Stopped)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            (await ReplyErrorLocalized("music_queue_stopped", Format.Code(Prefix + "play")).ConfigureAwait(false)).DeleteAfter(10);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        queuedMessage?.DeleteAfter(10);
 | 
					                        queuedMessage?.DeleteAfter(10);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    catch
 | 
					                    catch
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // ignored
 | 
					                        // ignored
 | 
				
			||||||
                    } // if queued message sending fails, don't attempt to delete it
 | 
					                    } 
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //todo  add play command. .play = .n, .play whatever = .q whatever
 | 
					        //todo  add play command. .play = .n, .play whatever = .q whatever
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
        [RequireContext(ContextType.Guild)]
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
        public async Task Queue([Remainder] string query)
 | 
					        public async Task Queue([Remainder] string query)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            //todo add a notice that player is stopped if user queues a song while it is
 | 
					 | 
				
			||||||
            var mp = await _music.GetOrCreatePlayer(Context);
 | 
					            var mp = await _music.GetOrCreatePlayer(Context);
 | 
				
			||||||
            var songInfo = await _music.ResolveSong(query, Context.User.ToString());
 | 
					            var songInfo = await _music.ResolveSong(query, Context.User.ToString());
 | 
				
			||||||
            await InternalQueue(mp, songInfo, false);
 | 
					            await InternalQueue(mp, songInfo, false);
 | 
				
			||||||
@@ -207,7 +205,7 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
                                return $"**⇒**`{number}.` {v.PrettyFullName}";
 | 
					                                return $"**⇒**`{number}.` {v.PrettyFullName}";
 | 
				
			||||||
                            else
 | 
					                            else
 | 
				
			||||||
                                return $"`{number}.` {v.PrettyFullName}";
 | 
					                                return $"`{number}.` {v.PrettyFullName}";
 | 
				
			||||||
                        })); //todo v.prettyfullname instead of title
 | 
					                        }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                desc = $"`🔊` {songs[current].PrettyFullName}\n\n" + desc;
 | 
					                desc = $"`🔊` {songs[current].PrettyFullName}\n\n" + desc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -687,7 +685,7 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
        [RequireContext(ContextType.Guild)]
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
        public async Task Move()
 | 
					        public void Move()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var vch = ((IGuildUser)Context.User).VoiceChannel;
 | 
					            var vch = ((IGuildUser)Context.User).VoiceChannel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -748,6 +746,7 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        //}
 | 
					        //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //todo test smq
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
        [RequireContext(ContextType.Guild)]
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
        public async Task SetMaxQueue(uint size = 0)
 | 
					        public async Task SetMaxQueue(uint size = 0)
 | 
				
			||||||
@@ -782,6 +781,7 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
        //        await ReplyConfirmLocalized("max_playtime_set", seconds).ConfigureAwait(false);
 | 
					        //        await ReplyConfirmLocalized("max_playtime_set", seconds).ConfigureAwait(false);
 | 
				
			||||||
        //}
 | 
					        //}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //todo test rcs
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
        [RequireContext(ContextType.Guild)]
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
        public async Task ReptCurSong()
 | 
					        public async Task ReptCurSong()
 | 
				
			||||||
@@ -803,6 +803,7 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
                                            .ConfigureAwait(false);
 | 
					                                            .ConfigureAwait(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //todo test rpl
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
        [RequireContext(ContextType.Guild)]
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
        public async Task RepeatPl()
 | 
					        public async Task RepeatPl()
 | 
				
			||||||
@@ -862,6 +863,7 @@ namespace NadekoBot.Modules.Music
 | 
				
			|||||||
                await ReplyConfirmLocalized("autoplay_enabled").ConfigureAwait(false);
 | 
					                await ReplyConfirmLocalized("autoplay_enabled").ConfigureAwait(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //todo test output text channel
 | 
				
			||||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
					        [NadekoCommand, Usage, Description, Aliases]
 | 
				
			||||||
        [RequireContext(ContextType.Guild)]
 | 
					        [RequireContext(ContextType.Guild)]
 | 
				
			||||||
        [RequireUserPermission(GuildPermission.ManageMessages)]
 | 
					        [RequireUserPermission(GuildPermission.ManageMessages)]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,48 +96,46 @@ namespace NadekoBot.Services.Music
 | 
				
			|||||||
                             var ac = await GetAudioClient();
 | 
					                             var ac = await GetAudioClient();
 | 
				
			||||||
                             if (ac == null)
 | 
					                             if (ac == null)
 | 
				
			||||||
                             {
 | 
					                             {
 | 
				
			||||||
                                 await Task.Delay(900);
 | 
					                                 await Task.Delay(900, cancelToken);
 | 
				
			||||||
                                 // just wait some time, maybe bot doesn't even have perms to join that voice channel, 
 | 
					                                 // just wait some time, maybe bot doesn't even have perms to join that voice channel, 
 | 
				
			||||||
                                 // i don't want to spam connection attempts
 | 
					                                 // i don't want to spam connection attempts
 | 
				
			||||||
                                 continue;
 | 
					                                 continue;
 | 
				
			||||||
                             }
 | 
					                             }
 | 
				
			||||||
                             using (var pcm = ac.CreatePCMStream(AudioApplication.Music))
 | 
					                             var pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 250);
 | 
				
			||||||
 | 
					                             OnStarted?.Invoke(this, data.Song);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                             byte[] buffer = new byte[3840];
 | 
				
			||||||
 | 
					                             int bytesRead = 0;
 | 
				
			||||||
 | 
					                             try
 | 
				
			||||||
                             {
 | 
					                             {
 | 
				
			||||||
                                 OnStarted?.Invoke(this, data.Song);
 | 
					                                 while ((bytesRead = await b.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) > 0)
 | 
				
			||||||
 | 
					                                 {
 | 
				
			||||||
 | 
					                                     var vol = Volume;
 | 
				
			||||||
 | 
					                                     if (vol != 1)
 | 
				
			||||||
 | 
					                                         AdjustVolume(buffer, vol);
 | 
				
			||||||
 | 
					                                     await Task.WhenAll(Task.Delay(10), pcm.WriteAsync(buffer, 0, bytesRead, cancelToken)).ConfigureAwait(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                 byte[] buffer = new byte[3840];
 | 
					                                     await (pauseTaskSource?.Task ?? Task.CompletedTask);
 | 
				
			||||||
                                 int bytesRead = 0;
 | 
					                                 }
 | 
				
			||||||
                                 try
 | 
					                             }
 | 
				
			||||||
                                 {
 | 
					                             catch (OperationCanceledException)
 | 
				
			||||||
                                     while ((bytesRead = await b.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) > 0)
 | 
					                             {
 | 
				
			||||||
                                     {
 | 
					                                 _log.Info("Song Canceled");
 | 
				
			||||||
                                         var vol = Volume;
 | 
					                             }
 | 
				
			||||||
                                         if (vol != 1)
 | 
					                             catch (Exception ex)
 | 
				
			||||||
                                             AdjustVolume(buffer, vol);
 | 
					                             {
 | 
				
			||||||
                                         await Task.WhenAll(Task.Delay(10), pcm.WriteAsync(buffer, 0, bytesRead, cancelToken)).ConfigureAwait(false);
 | 
					                                 _log.Warn(ex);
 | 
				
			||||||
 | 
					                             }
 | 
				
			||||||
 | 
					                             finally
 | 
				
			||||||
 | 
					                             {
 | 
				
			||||||
 | 
					                                 //flush is known to get stuck from time to time, just cancel it if it takes more than 1 second
 | 
				
			||||||
 | 
					                                 var flushCancel = new CancellationTokenSource();
 | 
				
			||||||
 | 
					                                 var flushToken = flushCancel.Token;
 | 
				
			||||||
 | 
					                                 var flushDelay = Task.Delay(1000, flushToken);
 | 
				
			||||||
 | 
					                                 await Task.WhenAny(flushDelay, pcm.FlushAsync(flushToken));
 | 
				
			||||||
 | 
					                                 flushCancel.Cancel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                         await (pauseTaskSource?.Task ?? Task.CompletedTask);
 | 
					                                 OnCompleted?.Invoke(this, data.Song);
 | 
				
			||||||
                                     }
 | 
					 | 
				
			||||||
                                 }
 | 
					 | 
				
			||||||
                                 catch (OperationCanceledException)
 | 
					 | 
				
			||||||
                                 {
 | 
					 | 
				
			||||||
                                     _log.Info("Song Canceled");
 | 
					 | 
				
			||||||
                                 }
 | 
					 | 
				
			||||||
                                 catch (Exception ex)
 | 
					 | 
				
			||||||
                                 {
 | 
					 | 
				
			||||||
                                     _log.Warn(ex);
 | 
					 | 
				
			||||||
                                 }
 | 
					 | 
				
			||||||
                                 finally
 | 
					 | 
				
			||||||
                                 {
 | 
					 | 
				
			||||||
                                     //flush is known to get stuck from time to time, just cancel it if it takes more than 1 second
 | 
					 | 
				
			||||||
                                     var flushCancel = new CancellationTokenSource();
 | 
					 | 
				
			||||||
                                     var flushToken = flushCancel.Token;
 | 
					 | 
				
			||||||
                                     var flushDelay = Task.Delay(1000, flushToken);
 | 
					 | 
				
			||||||
                                     await Task.WhenAny(flushDelay, pcm.FlushAsync(flushToken));
 | 
					 | 
				
			||||||
                                     flushCancel.Cancel();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                     OnCompleted?.Invoke(this, data.Song);
 | 
					 | 
				
			||||||
                                 }
 | 
					 | 
				
			||||||
                             }
 | 
					                             }
 | 
				
			||||||
                         }
 | 
					                         }
 | 
				
			||||||
                     }
 | 
					                     }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,7 @@ namespace NadekoBot.Services.Music
 | 
				
			|||||||
            song.ThrowIfNull(nameof(song));
 | 
					            song.ThrowIfNull(nameof(song));
 | 
				
			||||||
            lock (locker)
 | 
					            lock (locker)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if(CurrentIndex >= maxQueueSize)
 | 
					                if(maxQueueSize !=0 && CurrentIndex >= maxQueueSize)
 | 
				
			||||||
                    throw new PlaylistFullException();
 | 
					                    throw new PlaylistFullException();
 | 
				
			||||||
                Songs.AddLast(song);
 | 
					                Songs.AddLast(song);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -437,6 +437,7 @@
 | 
				
			|||||||
  "music_queued_song": "Queued song",
 | 
					  "music_queued_song": "Queued song",
 | 
				
			||||||
  "music_queue_cleared": "Music queue cleared.",
 | 
					  "music_queue_cleared": "Music queue cleared.",
 | 
				
			||||||
  "music_queue_full": "Queue is full at {0}/{0}.",
 | 
					  "music_queue_full": "Queue is full at {0}/{0}.",
 | 
				
			||||||
 | 
					  "music_queue_stopped": "Player is stopped. Use {0} command to start playing.",
 | 
				
			||||||
  "music_removed_song": "Removed song",
 | 
					  "music_removed_song": "Removed song",
 | 
				
			||||||
  "music_repeating_cur_song": "Repeating current song",
 | 
					  "music_repeating_cur_song": "Repeating current song",
 | 
				
			||||||
  "music_repeating_playlist": "Repeating playlist",
 | 
					  "music_repeating_playlist": "Repeating playlist",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user