Moved a part of music logic to a music service
This commit is contained in:
		@@ -76,10 +76,10 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    { "%servers%", () => NadekoBot.Client.Guilds.Count.ToString()},
 | 
			
		||||
                    { "%users%", () => NadekoBot.Client.Guilds.Sum(s => s.Users.Count).ToString()},
 | 
			
		||||
                    { "%playing%", () => {
 | 
			
		||||
                            var cnt = Music.Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
 | 
			
		||||
                            var cnt = NadekoBot.MusicService.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
 | 
			
		||||
                            if (cnt != 1) return cnt.ToString();
 | 
			
		||||
                            try {
 | 
			
		||||
                                var mp = Music.Music.MusicPlayers.FirstOrDefault();
 | 
			
		||||
                                var mp = NadekoBot.MusicService.MusicPlayers.FirstOrDefault();
 | 
			
		||||
                                return mp.Value.CurrentSong.SongInfo.Title;
 | 
			
		||||
                            }
 | 
			
		||||
                            catch {
 | 
			
		||||
@@ -87,7 +87,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    { "%queued%", () => Music.Music.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
 | 
			
		||||
                    { "%queued%", () => NadekoBot.MusicService.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
 | 
			
		||||
                    { "%time%", () => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
 | 
			
		||||
                    { "%shardcount%", () => NadekoBot.Client.Shards.Count.ToString() },
 | 
			
		||||
                };
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ using Newtonsoft.Json.Linq;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using NadekoBot.Services.Music;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Music
 | 
			
		||||
{
 | 
			
		||||
@@ -22,10 +23,10 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
    [DontAutoLoad]
 | 
			
		||||
    public class Music : NadekoTopLevelModule 
 | 
			
		||||
    {
 | 
			
		||||
        public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
 | 
			
		||||
 | 
			
		||||
        public const string MusicDataPath = "data/musicdata";
 | 
			
		||||
 | 
			
		||||
        private static MusicService music;
 | 
			
		||||
 | 
			
		||||
        static Music()
 | 
			
		||||
        {
 | 
			
		||||
            //it can fail if its currenctly opened or doesn't exist. Either way i don't care
 | 
			
		||||
@@ -34,6 +35,9 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            NadekoBot.Client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated;
 | 
			
		||||
 | 
			
		||||
            Directory.CreateDirectory(MusicDataPath);
 | 
			
		||||
 | 
			
		||||
            //todo move to service
 | 
			
		||||
            music = NadekoBot.MusicService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Task Client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState oldState, SocketVoiceState newState)
 | 
			
		||||
@@ -44,13 +48,11 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
            MusicPlayer player;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(usr.Guild.Id, out player))
 | 
			
		||||
            if ((player = music.GetPlayer(usr.Guild.Id)) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                //if bot moved
 | 
			
		||||
                if ((player.PlaybackVoiceChannel == oldState.VoiceChannel) &&
 | 
			
		||||
                        usr.Id == NadekoBot.Client.CurrentUser.Id)
 | 
			
		||||
@@ -92,7 +94,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            if (musicPlayer.PlaybackVoiceChannel == ((IGuildUser)Context.User).VoiceChannel)
 | 
			
		||||
            {
 | 
			
		||||
                while (--skipCount > 0)
 | 
			
		||||
@@ -109,7 +112,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public Task Stop()
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel == musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
            {
 | 
			
		||||
                musicPlayer.Autoplay = false;
 | 
			
		||||
@@ -123,10 +127,10 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public Task Destroy()
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel == musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                if (MusicPlayers.TryRemove(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
                    musicPlayer.Destroy();
 | 
			
		||||
                music.DestroyPlayer(Context.Guild.Id);
 | 
			
		||||
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
@@ -137,7 +141,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public Task Pause()
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            musicPlayer.TogglePause();
 | 
			
		||||
@@ -150,7 +155,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return;
 | 
			
		||||
            var val = musicPlayer.FairPlay = !musicPlayer.FairPlay;
 | 
			
		||||
@@ -169,7 +175,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Queue([Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query).ConfigureAwait(false);
 | 
			
		||||
            await music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query).ConfigureAwait(false);
 | 
			
		||||
            if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
 | 
			
		||||
            {
 | 
			
		||||
                Context.Message.DeleteAfter(10);
 | 
			
		||||
@@ -180,7 +186,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task SoundCloudQueue([Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
 | 
			
		||||
            await music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
 | 
			
		||||
            if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
 | 
			
		||||
            {
 | 
			
		||||
                Context.Message.DeleteAfter(10);
 | 
			
		||||
@@ -193,8 +199,9 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        {
 | 
			
		||||
            Song currentSong;
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer) ||
 | 
			
		||||
                (currentSong = musicPlayer?.CurrentSong) == null)
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            if ((currentSong = musicPlayer?.CurrentSong) == null)
 | 
			
		||||
            {
 | 
			
		||||
                await ReplyErrorLocalized("no_player").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -253,7 +260,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task NowPlaying()
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            var currentSong = musicPlayer.CurrentSong;
 | 
			
		||||
            if (currentSong == null)
 | 
			
		||||
@@ -274,7 +281,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task Volume(int val)
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return;
 | 
			
		||||
@@ -308,9 +315,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ShufflePlaylist()
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return;
 | 
			
		||||
@@ -362,7 +368,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                        return;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        await QueueSong(gusr, (ITextChannel)Context.Channel, gusr.VoiceChannel, id, true).ConfigureAwait(false);
 | 
			
		||||
                        await music.QueueSong(gusr, (ITextChannel)Context.Channel, gusr.VoiceChannel, id, true).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (SongNotFoundException) { }
 | 
			
		||||
                    catch { try { cancelSource.Cancel(); } catch { } }
 | 
			
		||||
@@ -388,17 +394,17 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            using (var http = new HttpClient())
 | 
			
		||||
            {
 | 
			
		||||
                var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientId}").ConfigureAwait(false))["tracks"].ToObject<SoundCloudVideo[]>();
 | 
			
		||||
                await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false);
 | 
			
		||||
                await music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                MusicPlayer mp;
 | 
			
		||||
                if (!MusicPlayers.TryGetValue(Context.Guild.Id, out mp))
 | 
			
		||||
                MusicPlayer musicPlayer;
 | 
			
		||||
                if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
                foreach (var svideo in scvids.Skip(1))
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        mp.AddSong(new Song(new SongInfo
 | 
			
		||||
                        musicPlayer.AddSong(new Song(new SongInfo
 | 
			
		||||
                        {
 | 
			
		||||
                            Title = svideo.FullName,
 | 
			
		||||
                            Provider = "SoundCloud",
 | 
			
		||||
@@ -429,7 +435,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await QueueSong(gusr, (ITextChannel)Context.Channel, gusr.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false);
 | 
			
		||||
                    await music.QueueSong(gusr, (ITextChannel)Context.Channel, gusr.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch (PlaylistFullException)
 | 
			
		||||
                {
 | 
			
		||||
@@ -453,7 +459,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                await ReplyErrorLocalized("must_be_in_voice").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, radioLink, musicType: MusicType.Radio).ConfigureAwait(false);
 | 
			
		||||
            await music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, radioLink, musicType: MusicType.Radio).ConfigureAwait(false);
 | 
			
		||||
            if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
 | 
			
		||||
            {
 | 
			
		||||
                Context.Message.DeleteAfter(10);
 | 
			
		||||
@@ -469,7 +475,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            var arg = path;
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(arg))
 | 
			
		||||
                return;
 | 
			
		||||
            await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false);
 | 
			
		||||
            await music.QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -491,7 +497,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public Task Remove(int num)
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
@@ -508,7 +514,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            if (all.Trim().ToUpperInvariant() != "ALL")
 | 
			
		||||
                return;
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return;
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            musicPlayer.ClearQueue();
 | 
			
		||||
            await ReplyConfirmLocalized("queue_cleared").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
@@ -521,9 +528,9 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            fromto = fromto?.Trim();
 | 
			
		||||
            var fromtoArr = fromto.Split('>');
 | 
			
		||||
 | 
			
		||||
@@ -564,7 +571,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task SetMaxQueue(uint size = 0)
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            musicPlayer.MaxQueueSize = size;
 | 
			
		||||
@@ -584,7 +591,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
            var channel = (ITextChannel)Context.Channel;
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            musicPlayer.MaxPlaytimeSeconds = seconds;
 | 
			
		||||
            if (seconds == 0)
 | 
			
		||||
@@ -597,9 +604,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ReptCurSong()
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            var currentSong = musicPlayer.CurrentSong;
 | 
			
		||||
            if (currentSong == null)
 | 
			
		||||
@@ -621,9 +627,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task RepeatPl()
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            var currentValue = musicPlayer.ToggleRepeatPlaylist();
 | 
			
		||||
            if(currentValue)
 | 
			
		||||
@@ -636,9 +641,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Save([Remainder] string name)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var curSong = musicPlayer.CurrentSong;
 | 
			
		||||
@@ -694,7 +698,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                var usr = (IGuildUser)Context.User;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await QueueSong(usr, (ITextChannel)Context.Channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false);
 | 
			
		||||
                    await music.QueueSong(usr, (ITextChannel)Context.Channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch (SongNotFoundException) { }
 | 
			
		||||
                catch { break; }
 | 
			
		||||
@@ -764,7 +768,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task Goto(int time)
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
            if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
                return;
 | 
			
		||||
@@ -799,7 +803,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task Autoplay()
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            if (!musicPlayer.ToggleAutoplay())
 | 
			
		||||
@@ -814,7 +818,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        public async Task SetMusicChannel()
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayer musicPlayer;
 | 
			
		||||
            if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
            if ((musicPlayer = music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
            {
 | 
			
		||||
                await ReplyErrorLocalized("no_player").ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
@@ -825,167 +829,5 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await ReplyConfirmLocalized("set_music_channel").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
 | 
			
		||||
        {
 | 
			
		||||
            if (voiceCh == null || voiceCh.Guild != textCh.Guild)
 | 
			
		||||
            {
 | 
			
		||||
                if (!silent)
 | 
			
		||||
                    await textCh.SendErrorAsync(GetText("must_be_in_voice")).ConfigureAwait(false);
 | 
			
		||||
                throw new ArgumentNullException(nameof(voiceCh));
 | 
			
		||||
            }
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
 | 
			
		||||
                throw new ArgumentException("Invalid song query.", nameof(query));
 | 
			
		||||
 | 
			
		||||
            var musicPlayer = MusicPlayers.GetOrAdd(textCh.Guild.Id, server =>
 | 
			
		||||
            {
 | 
			
		||||
                float vol;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    vol = uow.GuildConfigs.For(textCh.Guild.Id, set => set).DefaultMusicVolume;
 | 
			
		||||
                }
 | 
			
		||||
                var mp = new MusicPlayer(voiceCh, textCh, vol);
 | 
			
		||||
                IUserMessage playingMessage = null;
 | 
			
		||||
                IUserMessage lastFinishedMessage = null;
 | 
			
		||||
                mp.OnCompleted += async (s, song) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        lastFinishedMessage?.DeleteAfter(0);
 | 
			
		||||
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            lastFinishedMessage = await mp.OutputTextChannel.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                                    .WithAuthor(eab => eab.WithName(GetText("finished_song")).WithMusicIcon())
 | 
			
		||||
                                    .WithDescription(song.PrettyName)
 | 
			
		||||
                                    .WithFooter(ef => ef.WithText(song.PrettyInfo)))
 | 
			
		||||
                                .ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch
 | 
			
		||||
                        {
 | 
			
		||||
                            // ignored
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.ProviderType == MusicType.Normal)
 | 
			
		||||
                        {
 | 
			
		||||
                            var relatedVideos = (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList();
 | 
			
		||||
                            if(relatedVideos.Count > 0)
 | 
			
		||||
                            await QueueSong(await queuer.Guild.GetCurrentUserAsync(), 
 | 
			
		||||
                                textCh, 
 | 
			
		||||
                                voiceCh, 
 | 
			
		||||
                                relatedVideos[new NadekoRandom().Next(0, relatedVideos.Count)],
 | 
			
		||||
                                true).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mp.OnStarted += async (player, song) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                    var sender = player;
 | 
			
		||||
                    if (sender == null)
 | 
			
		||||
                        return;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        playingMessage?.DeleteAfter(0);
 | 
			
		||||
 | 
			
		||||
                        playingMessage = await mp.OutputTextChannel.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                                                    .WithAuthor(eab => eab.WithName(GetText("playing_song")).WithMusicIcon())
 | 
			
		||||
                                                    .WithDescription(song.PrettyName)
 | 
			
		||||
                                                    .WithFooter(ef => ef.WithText(song.PrettyInfo)))
 | 
			
		||||
                                                    .ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                mp.OnPauseChanged += async (paused) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        IUserMessage msg;
 | 
			
		||||
                        if (paused)
 | 
			
		||||
                            msg = await mp.OutputTextChannel.SendConfirmAsync(GetText("paused")).ConfigureAwait(false);
 | 
			
		||||
                        else
 | 
			
		||||
                            msg = await mp.OutputTextChannel.SendConfirmAsync(GetText("resumed")).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                        msg?.DeleteAfter(10);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                
 | 
			
		||||
                mp.SongRemoved += async (song, index) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var embed = new EmbedBuilder()
 | 
			
		||||
                            .WithAuthor(eab => eab.WithName(GetText("removed_song") + " #" + (index + 1)).WithMusicIcon())
 | 
			
		||||
                            .WithDescription(song.PrettyName)
 | 
			
		||||
                            .WithFooter(ef => ef.WithText(song.PrettyInfo))
 | 
			
		||||
                            .WithErrorColor();
 | 
			
		||||
 | 
			
		||||
                        await mp.OutputTextChannel.EmbedAsync(embed).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                return mp;
 | 
			
		||||
            });
 | 
			
		||||
            Song resolvedSong;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                musicPlayer.ThrowIfQueueFull();
 | 
			
		||||
                resolvedSong = await SongHandler.ResolveSong(query, musicType).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                if (resolvedSong == null)
 | 
			
		||||
                    throw new SongNotFoundException();
 | 
			
		||||
 | 
			
		||||
                musicPlayer.AddSong(resolvedSong, queuer.Username);
 | 
			
		||||
            }
 | 
			
		||||
            catch (PlaylistFullException)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await textCh.SendConfirmAsync(GetText("queue_full", musicPlayer.MaxQueueSize));
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    // ignored
 | 
			
		||||
                }
 | 
			
		||||
                throw;
 | 
			
		||||
            }
 | 
			
		||||
            if (!silent)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    //var queuedMessage = await textCh.SendConfirmAsync($"🎵 Queued **{resolvedSong.SongInfo.Title}** at `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
 | 
			
		||||
                    var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                                                            .WithAuthor(eab => eab.WithName(GetText("queued_song") + " #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon())
 | 
			
		||||
                                                            .WithDescription($"{resolvedSong.PrettyName}\n{GetText("queue")} ")
 | 
			
		||||
                                                            .WithThumbnailUrl(resolvedSong.Thumbnail)
 | 
			
		||||
                                                            .WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider)))
 | 
			
		||||
                                                            .ConfigureAwait(false);
 | 
			
		||||
                    queuedMessage?.DeleteAfter(10);
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    // ignored
 | 
			
		||||
                } // if queued message sending fails, don't attempt to delete it
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -418,8 +418,8 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                            NadekoBot.Client.Guilds.Count, stats.TextChannels, stats.VoiceChannels)).WithIsInline(true))
 | 
			
		||||
#if !GLOBAL_NADEKO
 | 
			
		||||
                    .WithFooter(efb => efb.WithText(GetText("stats_songs",
 | 
			
		||||
                        Music.Music.MusicPlayers.Count(mp => mp.Value.CurrentSong != null),
 | 
			
		||||
                        Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count))))
 | 
			
		||||
                        NadekoBot.MusicService.MusicPlayers.Count(mp => mp.Value.CurrentSong != null),
 | 
			
		||||
                        NadekoBot.MusicService.MusicPlayers.Sum(mp => mp.Value.Playlist.Count))))
 | 
			
		||||
#endif
 | 
			
		||||
                    );
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ using System.Diagnostics;
 | 
			
		||||
using NadekoBot.Modules.Music;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using NadekoBot.Services.Music;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot
 | 
			
		||||
{
 | 
			
		||||
@@ -49,6 +50,7 @@ namespace NadekoBot
 | 
			
		||||
        //services
 | 
			
		||||
        //todo DI in the future
 | 
			
		||||
        public static GreetSettingsService GreetSettingsService { get; private set; }
 | 
			
		||||
        public static MusicService MusicService { get; private set; }
 | 
			
		||||
 | 
			
		||||
        static NadekoBot()
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
@@ -36,6 +37,41 @@ namespace NadekoBot.Services
 | 
			
		||||
            return settings;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<bool> SetSettings(ulong guildId, GreetSettings settings)
 | 
			
		||||
        {
 | 
			
		||||
            if (settings.AutoDeleteByeMessagesTimer > 600 ||
 | 
			
		||||
                settings.AutoDeleteByeMessagesTimer < 0 ||
 | 
			
		||||
                settings.AutoDeleteGreetMessagesTimer > 600 ||
 | 
			
		||||
                settings.AutoDeleteGreetMessagesTimer < 0)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                var conf = uow.GuildConfigs.For(guildId, set => set);
 | 
			
		||||
                conf.DmGreetMessageText = settings.DmGreetMessageText?.SanitizeMentions();
 | 
			
		||||
                conf.ChannelGreetMessageText = settings.ChannelGreetMessageText?.SanitizeMentions();
 | 
			
		||||
                conf.ChannelByeMessageText = settings.ChannelByeMessageText?.SanitizeMentions();
 | 
			
		||||
 | 
			
		||||
                conf.AutoDeleteGreetMessagesTimer = settings.AutoDeleteGreetMessagesTimer;
 | 
			
		||||
                conf.AutoDeleteGreetMessages = settings.AutoDeleteGreetMessagesTimer > 0;
 | 
			
		||||
 | 
			
		||||
                conf.AutoDeleteByeMessagesTimer = settings.AutoDeleteByeMessagesTimer;
 | 
			
		||||
                conf.AutoDeleteByeMessages = settings.AutoDeleteByeMessagesTimer > 0;
 | 
			
		||||
 | 
			
		||||
                conf.GreetMessageChannelId = settings.GreetMessageChannelId;
 | 
			
		||||
                conf.ByeMessageChannelId = settings.ByeMessageChannelId;
 | 
			
		||||
 | 
			
		||||
                conf.SendChannelGreetMessage = settings.SendChannelGreetMessage;
 | 
			
		||||
                conf.SendChannelByeMessage = settings.SendChannelByeMessage;
 | 
			
		||||
 | 
			
		||||
                await uow.CompleteAsync().ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
 | 
			
		||||
        {
 | 
			
		||||
            bool enabled;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ using NLog;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    public enum MusicType
 | 
			
		||||
    {
 | 
			
		||||
        Radio,
 | 
			
		||||
							
								
								
									
										213
									
								
								src/NadekoBot/Services/Music/MusicService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								src/NadekoBot/Services/Music/MusicService.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using NadekoBot.Modules.Music.Classes;
 | 
			
		||||
using Discord;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Modules;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Music
 | 
			
		||||
{
 | 
			
		||||
    public class MusicService
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IGoogleApiService _google;
 | 
			
		||||
        public ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
 | 
			
		||||
 | 
			
		||||
        public MusicService(IGoogleApiService google)
 | 
			
		||||
        {
 | 
			
		||||
            _google = google;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public MusicPlayer GetPlayer(ulong guildId)
 | 
			
		||||
        {
 | 
			
		||||
            MusicPlayers.TryGetValue(guildId, out var player);
 | 
			
		||||
            return player;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public MusicPlayer GetOrCreatePlayer(ulong guildId, IVoiceChannel voiceCh, ITextChannel textCh)
 | 
			
		||||
        {
 | 
			
		||||
            string GetText(string text, params object[] replacements) =>
 | 
			
		||||
                NadekoTopLevelModule.GetTextStatic(text, NadekoBot.Localization.GetCultureInfo(textCh.Guild), nameof(Modules.Music.Music).ToLowerInvariant(), replacements);
 | 
			
		||||
 | 
			
		||||
            return MusicPlayers.GetOrAdd(guildId, server =>
 | 
			
		||||
            {
 | 
			
		||||
                float vol;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    //todo move to cached variable
 | 
			
		||||
                    vol = uow.GuildConfigs.For(guildId, set => set).DefaultMusicVolume;
 | 
			
		||||
                }
 | 
			
		||||
                var mp = new MusicPlayer(voiceCh, textCh, vol);
 | 
			
		||||
                IUserMessage playingMessage = null;
 | 
			
		||||
                IUserMessage lastFinishedMessage = null;
 | 
			
		||||
                mp.OnCompleted += async (s, song) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        lastFinishedMessage?.DeleteAfter(0);
 | 
			
		||||
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            lastFinishedMessage = await mp.OutputTextChannel.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                                    .WithAuthor(eab => eab.WithName(GetText("finished_song")).WithMusicIcon())
 | 
			
		||||
                                    .WithDescription(song.PrettyName)
 | 
			
		||||
                                    .WithFooter(ef => ef.WithText(song.PrettyInfo)))
 | 
			
		||||
                                .ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        catch
 | 
			
		||||
                        {
 | 
			
		||||
                            // ignored
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.ProviderType == MusicType.Normal)
 | 
			
		||||
                        {
 | 
			
		||||
                            var relatedVideos = (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList();
 | 
			
		||||
                            if (relatedVideos.Count > 0)
 | 
			
		||||
                                await QueueSong(await textCh.Guild.GetCurrentUserAsync(),
 | 
			
		||||
                                    textCh,
 | 
			
		||||
                                    voiceCh,
 | 
			
		||||
                                    relatedVideos[new NadekoRandom().Next(0, relatedVideos.Count)],
 | 
			
		||||
                                    true).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mp.OnStarted += async (player, song) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                    var sender = player;
 | 
			
		||||
                    if (sender == null)
 | 
			
		||||
                        return;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        playingMessage?.DeleteAfter(0);
 | 
			
		||||
 | 
			
		||||
                        playingMessage = await mp.OutputTextChannel.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                                                    .WithAuthor(eab => eab.WithName(GetText("playing_song")).WithMusicIcon())
 | 
			
		||||
                                                    .WithDescription(song.PrettyName)
 | 
			
		||||
                                                    .WithFooter(ef => ef.WithText(song.PrettyInfo)))
 | 
			
		||||
                                                    .ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                mp.OnPauseChanged += async (paused) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        IUserMessage msg;
 | 
			
		||||
                        if (paused)
 | 
			
		||||
                            msg = await mp.OutputTextChannel.SendConfirmAsync(GetText("paused")).ConfigureAwait(false);
 | 
			
		||||
                        else
 | 
			
		||||
                            msg = await mp.OutputTextChannel.SendConfirmAsync(GetText("resumed")).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                        msg?.DeleteAfter(10);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mp.SongRemoved += async (song, index) =>
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        var embed = new EmbedBuilder()
 | 
			
		||||
                            .WithAuthor(eab => eab.WithName(GetText("removed_song") + " #" + (index + 1)).WithMusicIcon())
 | 
			
		||||
                            .WithDescription(song.PrettyName)
 | 
			
		||||
                            .WithFooter(ef => ef.WithText(song.PrettyInfo))
 | 
			
		||||
                            .WithErrorColor();
 | 
			
		||||
 | 
			
		||||
                        await mp.OutputTextChannel.EmbedAsync(embed).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                    catch
 | 
			
		||||
                    {
 | 
			
		||||
                        // ignored
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                return mp;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
 | 
			
		||||
        {
 | 
			
		||||
            string GetText(string text, params object[] replacements) => 
 | 
			
		||||
                NadekoTopLevelModule.GetTextStatic(text, NadekoBot.Localization.GetCultureInfo(textCh.Guild), nameof(Modules.Music.Music).ToLowerInvariant(), replacements);
 | 
			
		||||
 | 
			
		||||
            if (voiceCh == null || voiceCh.Guild != textCh.Guild)
 | 
			
		||||
            {
 | 
			
		||||
                if (!silent)
 | 
			
		||||
                    await textCh.SendErrorAsync(GetText("must_be_in_voice")).ConfigureAwait(false);
 | 
			
		||||
                throw new ArgumentNullException(nameof(voiceCh));
 | 
			
		||||
            }
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
 | 
			
		||||
                throw new ArgumentException("Invalid song query.", nameof(query));
 | 
			
		||||
 | 
			
		||||
            var musicPlayer = GetOrCreatePlayer(textCh.Guild.Id, voiceCh, textCh);
 | 
			
		||||
            Song resolvedSong;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                musicPlayer.ThrowIfQueueFull();
 | 
			
		||||
                resolvedSong = await SongHandler.ResolveSong(query, musicType).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                if (resolvedSong == null)
 | 
			
		||||
                    throw new SongNotFoundException();
 | 
			
		||||
 | 
			
		||||
                musicPlayer.AddSong(resolvedSong, queuer.Username);
 | 
			
		||||
            }
 | 
			
		||||
            catch (PlaylistFullException)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await textCh.SendConfirmAsync(GetText("queue_full", musicPlayer.MaxQueueSize));
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    // ignored
 | 
			
		||||
                }
 | 
			
		||||
                throw;
 | 
			
		||||
            }
 | 
			
		||||
            if (!silent)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    //var queuedMessage = await textCh.SendConfirmAsync($"🎵 Queued **{resolvedSong.SongInfo.Title}** at `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
 | 
			
		||||
                    var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
 | 
			
		||||
                                                            .WithAuthor(eab => eab.WithName(GetText("queued_song") + " #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon())
 | 
			
		||||
                                                            .WithDescription($"{resolvedSong.PrettyName}\n{GetText("queue")} ")
 | 
			
		||||
                                                            .WithThumbnailUrl(resolvedSong.Thumbnail)
 | 
			
		||||
                                                            .WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider)))
 | 
			
		||||
                                                            .ConfigureAwait(false);
 | 
			
		||||
                    queuedMessage?.DeleteAfter(10);
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    // ignored
 | 
			
		||||
                } // if queued message sending fails, don't attempt to delete it
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void DestroyPlayer(ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user