diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs index 8f80e726..4d3584c5 100644 --- a/src/NadekoBot/Modules/Music/Music.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -75,7 +75,6 @@ namespace NadekoBot.Modules.Music return; } - ////if some other user moved //if ((player.VoiceChannel == newState.VoiceChannel && //if joined first, and player paused, unpause // player.Paused && @@ -232,7 +231,8 @@ namespace NadekoBot.Modules.Music if (--page < -1) return; - //try { await musicPlayer.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { } + + try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { } const int itemsPerPage = 10; @@ -604,13 +604,13 @@ namespace NadekoBot.Modules.Music var (_, currentSong) = mp.Current; if (currentSong == null) return; - //try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { } + try { await mp.UpdateSongDurationsAsync().ConfigureAwait(false); } catch { } var embed = new EmbedBuilder().WithOkColor() .WithAuthor(eab => eab.WithName(GetText("now_playing")).WithMusicIcon()) .WithDescription(currentSong.PrettyName) .WithThumbnailUrl(currentSong.Thumbnail) - .WithFooter(ef => ef.WithText(mp.PrettyVolume + " | " + /*currentSong.PrettyFullTime +*/ $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}")); + .WithFooter(ef => ef.WithText(mp.PrettyVolume + " | " + mp.PrettyFullTime + $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}")); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); } @@ -847,7 +847,7 @@ namespace NadekoBot.Modules.Music else await ReplyConfirmLocalized("rpl_disabled").ConfigureAwait(false); } - + //todo readd goto //[NadekoCommand, Usage, Description, Aliases] //[RequireContext(ContextType.Guild)] //public async Task Goto(int time) diff --git a/src/NadekoBot/Services/Music/MusicPlayer.cs b/src/NadekoBot/Services/Music/MusicPlayer.cs index fc11e1ab..9dd806e1 100644 --- a/src/NadekoBot/Services/Music/MusicPlayer.cs +++ b/src/NadekoBot/Services/Music/MusicPlayer.cs @@ -7,6 +7,7 @@ using NLog; using System.Linq; using System.Collections.Concurrent; using NadekoBot.Extensions; +using System.Diagnostics; namespace NadekoBot.Services.Music { @@ -28,10 +29,24 @@ namespace NadekoBot.Services.Music public bool Exited { get; set; } = false; public bool Stopped { get; private set; } = false; public float Volume { get; private set; } = 1.0f; - public string PrettyVolume => $"🔉 {(int)(Volume * 100)}%"; public bool Paused => pauseTaskSource != null; private TaskCompletionSource pauseTaskSource { get; set; } = null; + public string PrettyVolume => $"🔉 {(int)(Volume * 100)}%"; + public string PrettyCurrentTime + { + get + { + var time = CurrentTime.ToString(@"mm\:ss"); + var hrs = (int)CurrentTime.TotalHours; + + if (hrs > 0) + return hrs + ":" + time; + else + return time; + } + } + public string PrettyFullTime => PrettyCurrentTime + " / " + (Queue.Current.Song?.PrettyTotalTime ?? "?"); private CancellationTokenSource SongCancelSource { get; set; } public ITextChannel OutputTextChannel { get; set; } public (int Index, SongInfo Current) Current @@ -96,11 +111,12 @@ namespace NadekoBot.Services.Music private bool manualSkip = false; private bool manualIndex = false; private bool newVoiceChannel = false; + private readonly IGoogleApiService _google; private ConcurrentHashSet RecentlyPlayedUsers { get; } = new ConcurrentHashSet(); public TimeSpan TotalPlaytime => TimeSpan.MaxValue; - public MusicPlayer(MusicService musicService, IVoiceChannel vch, ITextChannel output, float volume) + public MusicPlayer(MusicService musicService, IGoogleApiService google, IVoiceChannel vch, ITextChannel output, float volume) { _log = LogManager.GetCurrentClassLogger(); this.Volume = volume; @@ -108,6 +124,7 @@ namespace NadekoBot.Services.Music this.SongCancelSource = new CancellationTokenSource(); this.OutputTextChannel = output; this._musicService = musicService; + this._google = google; _player = Task.Run(async () => { @@ -530,6 +547,30 @@ namespace NadekoBot.Services.Music } } + public async Task UpdateSongDurationsAsync() + { + var sw = Stopwatch.StartNew(); + var (_, songs) = Queue.ToArray(); + var toUpdate = songs + .Where(x => x.ProviderType == Database.Models.MusicType.YouTube + && x.TotalTime == TimeSpan.Zero); + + var vIds = toUpdate.Select(x => x.VideoId); + + sw.Stop(); + _log.Info(sw.Elapsed.TotalSeconds); + if (!vIds.Any()) + return; + + var durations = await _google.GetVideoDurationsAsync(vIds); + + foreach (var x in toUpdate) + { + if (durations.TryGetValue(x.VideoId, out var dur)) + x.TotalTime = dur; + } + } + //// this should be written better //public TimeSpan TotalPlaytime => // _playlist.Any(s => s.TotalTime == TimeSpan.MaxValue) ? diff --git a/src/NadekoBot/Services/Music/MusicService.cs b/src/NadekoBot/Services/Music/MusicService.cs index 2ed203ac..bcd00b29 100644 --- a/src/NadekoBot/Services/Music/MusicService.cs +++ b/src/NadekoBot/Services/Music/MusicService.cs @@ -88,7 +88,7 @@ namespace NadekoBot.Services.Music return MusicPlayers.GetOrAdd(guildId, _ => { var vol = GetDefaultVolume(guildId); - var mp = new MusicPlayer(this, voiceCh, textCh, vol); + var mp = new MusicPlayer(this, _google, voiceCh, textCh, vol); IUserMessage playingMessage = null; IUserMessage lastFinishedMessage = null; diff --git a/src/NadekoBot/Services/Music/SongBuffer.cs b/src/NadekoBot/Services/Music/SongBuffer.cs index 0bf6f089..af6bac8b 100644 --- a/src/NadekoBot/Services/Music/SongBuffer.cs +++ b/src/NadekoBot/Services/Music/SongBuffer.cs @@ -53,7 +53,7 @@ namespace NadekoBot.Services.Music _log.Error(">>> " + e.Data); if (e.Data?.Contains("Error in the pull function") == true) { - _log.Info("Got error in the pull function!"); + _log.Error("Ignore this."); restart = true; } } @@ -108,15 +108,12 @@ namespace NadekoBot.Services.Music //_log.Info(_outStream.Length); await Task.Delay(10); } - if (cancelToken.IsCancellationRequested) - _log.Info("Song canceled"); - else if (p.HasExited) - _log.Info("Song buffered completely (FFmpeg exited)"); - else if (bytesRead == 0) - _log.Info("Nothing read"); - - if (restart) - _log.Info("Lets do some magix"); + //if (cancelToken.IsCancellationRequested) + // _log.Info("Song canceled"); + //else if (p.HasExited) + // _log.Info("Song buffered completely (FFmpeg exited)"); + //else if (bytesRead == 0) + // _log.Info("Nothing read"); //} //while (restart && !cancelToken.IsCancellationRequested); } diff --git a/src/NadekoBot/Services/Music/SongInfo.cs b/src/NadekoBot/Services/Music/SongInfo.cs index 22accf2f..04d48d55 100644 --- a/src/NadekoBot/Services/Music/SongInfo.cs +++ b/src/NadekoBot/Services/Music/SongInfo.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Services.Music public string Uri { get; set; } public string AlbumArt { get; set; } public string QueuerName { get; set; } - public TimeSpan TotalTime = TimeSpan.Zero; + public TimeSpan TotalTime { get; set; } = TimeSpan.Zero; public string PrettyProvider => (Provider ?? "???"); //public string PrettyFullTime => PrettyCurrentTime + " / " + PrettyTotalTime; @@ -60,7 +60,20 @@ namespace NadekoBot.Services.Music } } } - private string videoId = null; + private string _videoId = null; + public string VideoId + { + get + { + if (ProviderType == MusicType.YouTube) + return _videoId = _videoId ?? videoIdRegex.Match(Query)?.ToString(); + + return _videoId ?? ""; + } + + set => _videoId = value; + } + private readonly Regex videoIdRegex = new Regex("<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+", RegexOptions.Compiled); public string Thumbnail { @@ -71,8 +84,7 @@ namespace NadekoBot.Services.Music case MusicType.Radio: return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links case MusicType.YouTube: - videoId = videoId ?? videoIdRegex.Match(Query)?.ToString(); - return $"https://img.youtube.com/vi/{ videoId }/0.jpg"; + return $"https://img.youtube.com/vi/{ VideoId }/0.jpg"; case MusicType.Local: return "https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links case MusicType.Soundcloud: