public static string GetYTVideoId(string url) { try { return(VideoId.TryParse(url)?.Value); } catch (Exception) { return(""); } }
public void I_can_specify_a_valid_video_url_in_place_of_an_id(string videoUrl, string expectedVideoId) { // Act var result = new VideoId(videoUrl); var maybeResult = VideoId.TryParse(videoUrl); // Assert result.Value.Should().Be(expectedVideoId); maybeResult.Should().Be(result); }
public void I_can_specify_a_valid_video_id(string videoId) { // Act var result = new VideoId(videoId); var maybeResult = VideoId.TryParse(videoId); // Assert result.Value.Should().Be(videoId); maybeResult.Should().Be(result); }
public void I_cannot_specify_an_invalid_video_url_in_place_of_an_id(string videoUrl) { // Act & assert Assert.Throws <ArgumentException>(() => new VideoId(videoUrl)); VideoId.TryParse(videoUrl).Should().BeNull(); }
public async Task PlayAsync(params string[] Args) { if (Client.State == PlayerState.Paused) { Client.State = PlayerState.Playing; return; } EmbedBuilder Builder = new EmbedBuilder() { Color = Client.Color, Title = GetEntry("Enqueue") }; if (Args.Length > 0) { if (Args[0] == "soundcloud" && Args.Length > 1) { if (Args[1] == "playlist" && Args.Length > 2) { List <Models.SoundCloud.Playlist> playlists = Client.SearchSoundCloudPlaylist(string.Join(" ", Args.Skip(2))); Models.SoundCloud.Playlist playlist = await Global.MusicHandler.Select(Client, playlists, Context, Language); if (playlist == null) { Builder.Description = GetEntry("SCPlaylistCancelled"); await Context.Channel.SendMessageAsync("", embed : Builder.Build()); } else { Client.Enqueue(playlist); Builder.Url = playlist.Url; Builder.Description = GetEntry("SCPlaylistEnqueued"); Builder.AddField(GetEntry("TitleTrackCount"), playlist.Title + " | " + playlist.TrackCount); Builder.AddField(GetEntry("PlaylistMadeBy"), playlist.User.Username); Builder.ThumbnailUrl = playlist.ThumbnailUrl; await Context.Channel.SendMessageAsync("", embed : Builder.Build()); if (Client.State < PlayerState.Playing) { await Client.PlayAsync(Context); } } } else { List <Models.SoundCloud.Track> tracks = Client.SearchSoundCloudTrack(string.Join(" ", Args.Skip(1))); Models.SoundCloud.Track track = await Global.MusicHandler.Select(Client, tracks, Context, Language); if (track == null) { Builder.Description = GetEntry("SCTrackCancelled"); await Context.Channel.SendMessageAsync("", embed : Builder.Build()); } else { Client.Enqueue(track); if (Client.State < PlayerState.Playing) { await Client.PlayAsync(Context); } else { Builder.Url = track.Url; Builder.Description = GetEntry("SCTrackEnqueued"); Builder.AddField(GetEntry("TitleUploadedBy"), track.Title + " | " + track.User.Username); Builder.ThumbnailUrl = track.ThumbnailUrl; await Context.Channel.SendMessageAsync("", embed : Builder.Build()); } } } } else if (Args[0].ToLower() == "listen.moe") { Client.EnqueueLISTENmoe(Args.Length > 1 && Args[1].ToLower() == "kpop"); Builder.Description = "LISTEN.moe"; await Context.Channel.SendMessageAsync("", embed : Builder.Build()); if (Client.State < PlayerState.Playing) { await Client.PlayAsync(Context); } } else { string url = string.Join(" ", Args); YoutubeClient client = new YoutubeClient(); PlaylistId? id = PlaylistId.TryParse(url); if (id.HasValue) { List <PlaylistVideo> videos = await client.Playlists.GetVideosAsync(id.Value).ToListAsync(); if (videos.Count == 0) { Builder.Description = GetEntry("YTPlaylistEmpty"); await Context.Channel.SendMessageAsync("", embed : Builder.Build()); } else { YoutubeExplode.Playlists.Playlist playlist = await client.Playlists.GetAsync(id.Value); Client.Enqueue(playlist); if (Client.State < PlayerState.Playing) { await Client.PlayAsync(Context); } else { Builder.Url = playlist.Url; Builder.Description = GetEntry("YTPlaylistEnqueued"); Builder.AddField(GetEntry("TitleUploadedBy"), playlist.Title + " | " + playlist.Author); Builder.ThumbnailUrl = videos[0].Thumbnails.GetMaxResUrl(); await Context.Channel.SendMessageAsync("", embed : Builder.Build()); } } } VideoId?vid = VideoId.TryParse(url); if (vid.HasValue) { Video video = await client.Videos.GetAsync(vid.Value); await EnqueueVideo(video, Builder); } else { List <VideoSearchResult> videos = await Client.SearchYouTubeVideoAsync(url); VideoSearchResult video = await Global.MusicHandler.Select(Client, videos, Context, Language); if (video == null) { Builder.Description = GetEntry("YTVideoCancelled"); await Context.Channel.SendMessageAsync("", embed : Builder.Build()); } else { await EnqueueVideo(video, Builder); } } } } else { if (Client.Queue.Count != 0 && Client.State < PlayerState.Playing) { await Client.PlayAsync(Context); } else { await Context.Channel.SendMessageAsync(GetEntry("Empty")); } } }
public async Task PlayAsync(ICommandContext Context, ITextChannel Channel = null, bool KeepCurrent = false, TimeSpan?SeekTo = null, bool AvoidState = false) { if (Channel == null) { Channel = Context.Channel as ITextChannel; } string lId = Channel.GetSettings().Language; LanguageEntry Language = Global.Languages.GetLanguage(lId); if (!AvoidState) { if (State == PlayerState.Playing || State == PlayerState.Paused) { await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:AlreadyPlaying")); return; } } if (State == PlayerState.Disconnected) { bool Success = await ConnectAsync(Context); if (!Success) { return; } } if (!KeepCurrent || Current == null) { Current = Queue[QueueIndex]; } string Url = Current.UrlOrId; WebSocket ws = null; if (Current.IsYouTube) { YoutubeClient Client = new YoutubeClient(); StreamManifest sm = null; try { sm = await Client.Videos.Streams.GetManifestAsync(VideoId.TryParse(Current.UrlOrId).Value); } catch (Exception e) { File.WriteAllText("tempexceptionfrommusicplayer.json", JsonConvert.SerializeObject(e, Formatting.Indented)); await Global.Client.GetGuild(Global.Settings.DevServer.Id) .GetTextChannel(Global.Settings.DevServer.ErrorReportChannelId).SendFileAsync("tempexceptionfrommusicplayer.json", ""); File.Delete("tempexceptionfrommusicplayer.json"); } if (sm != null) { IEnumerable <IAudioStreamInfo> streamInfos = sm.GetAudioStreams(); if (streamInfos.Count() > 0) { IStreamInfo info = streamInfos.GetWithHighestBitrate(); Url = info.Url; } } if (Url == Current.UrlOrId) { Url = null; } } else { if (Current.IsListenMoe) { Url = Current.PublicUrl; ws = new WebSocket(Current.PublicUrl.Contains("kpop") ? "wss://listen.moe/kpop/gateway_v2" : "wss://listen.moe/gateway_v2"); Timer t = new Timer((state) => { try { ws.Send("{ \"op\": 9 }"); } catch { Logger.Log(LogType.WebSocket, ConsoleColor.Red, "Error", "Couldn't send heartbeat to LISTEN.moe!"); } }, null, -1, -1); ws.OnOpen += (s, e) => { ws.Send("{ \"op\": 0, \"d\": { \"auth\": \"\" } }"); // { op: 0, d: { auth: "" } } }; ws.OnMessage += (s, e) => { ListenMoe parsed = JsonConvert.DeserializeObject <ListenMoe>(e.Data); if (parsed.OpCode == 0) { t.Change(0, parsed.Data.HeartBeat); } else if (parsed.OpCode == 1 && parsed.Type == "TRACK_UPDATE") { ListenMoeStartTime = parsed.Data.StartTime; Current.Author = string.Join(" && ", parsed.Data.Song.Artists.Select(i => i.NameRomaji ?? i.Name)); Current.Duration = TimeSpan.FromSeconds(parsed.Data.Song.Duration); Current.Title = parsed.Data.Song.Title; Current.Thumbnail = null; foreach (ListenMoeAlbum album in parsed.Data.Song.Albums) { if (album.Image != null) { Current.Thumbnail = album.Image; break; } } if (State > PlayerState.Connected && State != PlayerState.Paused) { SendNowPlayingAsync(Context, Channel).GetAwaiter().GetResult(); } } }; ws.OnClose += (s, e) => { t.Change(Timeout.Infinite, Timeout.Infinite); t.Dispose(); }; ws.Connect(); } else if (Global.SoundCloud == null) { if (!IterateIndex(true)) { Current = null; await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:SoundCloudNotAvailable")); } else { await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:OnlySoundCloudTracks")); new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)); } return; } else { Url += "?client_id=" + Global.SoundCloud.ClientId; } } if (Url == null) { if (!IterateIndex()) { Current = null; await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:FinishedPlaying")); State = PlayerState.Connected; } else { new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)).Start(); return; } } try { Reader = new FFmpegReader(Url); /* * switch (encoding.Name) * { * case "webm": * case "3gpp": * Stream s = await new HttpClient().GetStreamAsync(Url); * Reader = new NAudio.Vorbis.VorbisWaveReader(s); * break; * * default: * Reader = new MediaFoundationReader(Url); * break; * } */ } catch (Exception e) { System.Console.WriteLine(e); await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:SongInaccessible", "SONGNAME", Current.Title)); if (!IterateIndex(Global.SoundCloud == null)) { Current = null; await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:FinishedPlaying")); State = PlayerState.Connected; } else { new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)).Start(); } return; } if (PCMStream == null || !PCMStream.CanWrite) { PCMStream = Client.CreatePCMStream(AudioApplication.Music, 128 * 1024, 200, 0); } //WaveFormat OutFormat = new WaveFormat(48000, 16, 2); /* * MediaFoundationResampler Resampler = new MediaFoundationResampler(Reader, OutFormat) * { * ResamplerQuality = 60 * }; */ //if (SeekTo.HasValue && !Current.IsListenMoe) Reader.CurrentTime = SeekTo.Value; if (SeekTo.HasValue && SeekTo != TimeSpan.Zero && !Current.IsListenMoe) { Reader.ReadUntil(SeekTo.Value); } BackupTime = TimeSpan.Zero; //int Size = OutFormat.AverageBytesPerSecond / 50; int Size = Reader.BufferSize(1); byte[] Buffer = new byte[Size]; int Count = 0; State = PlayerState.Playing; TextChannelId = Channel.Id; if (!Current.IsListenMoe) { await SendNowPlayingAsync(Context, Channel); } /*while (Reader.CanRead && (Count = Resampler.Read(Buffer, 0, Size)) > 0 * && Request == PlayerRequest.Idle && State > PlayerState.Connected)*/ while (Reader.CanRead && (Count = Reader.Read(Buffer, 0, Size)) > 0 && Request == PlayerRequest.Idle && State > PlayerState.Connected) { if (State == PlayerState.Paused) { await Channel.SendMessageAsync("", embed : new EmbedBuilder() { Title = Language.GetEntry("MusicHandler:Paused"), Color = Color }.Build()); while (State == PlayerState.Paused && Request == PlayerRequest.Idle) { Thread.Sleep(100); } string cId = Channel.GetSettings().Language; if (cId != lId) { Language = Global.Languages.GetLanguage(cId); } lId = cId; if (State == PlayerState.Playing) { await Channel.SendMessageAsync("", embed : new EmbedBuilder() { Title = Language.GetEntry("MusicHandler:Resumed"), Color = Color }.Build()); if (Current.IsListenMoe) { await SendNowPlayingAsync(Context, Channel); } } } if (Request > 0) { break; } if (CurrentTime.TotalSeconds % 10 == 0 && BackupTime.TotalSeconds != CurrentTime.TotalSeconds) { PropertyChanged?.Invoke(); BackupTime = CurrentTime; } try { if (State < PlayerState.Playing) { break; } ChangeVolume(Buffer, Volume / 100f); await PCMStream.WriteAsync(Buffer, 0, Count); } catch (Exception e) { if (State == PlayerState.Disconnected || Client.ConnectionState == ConnectionState.Disconnected || Client.ConnectionState == ConnectionState.Disconnecting) { break; } string cId = Channel.GetSettings().Language; if (cId != lId) { Language = Global.Languages.GetLanguage(cId); } lId = cId; await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:PlaybackErrorOccured")); Request = PlayerRequest.Stop; Logger.Log(LogType.Music, ConsoleColor.Red, "Error", e.ToString()); if (Global.Settings.DevServer.ErrorReportChannelId != 0) { ITextChannel Report = Global.Client.GetChannel(Global.Settings.DevServer.ErrorReportChannelId) as ITextChannel; await Report.SendMessageAsync($"An error occured while playing on a server!\n```\n{ e }\n```\n" + $"Client:\n { JsonConvert.SerializeObject(this) }"); } break; } } if (ws != null && ws.IsAlive) { ws.Close(); } if (Request == PlayerRequest.Idle && State > PlayerState.Connected) { Request = PlayerRequest.Next; } //Resampler.Dispose(); Reader.Dispose(); Reader = null; //Resampler = null; try { await PCMStream.FlushAsync(); } catch { } // It may be disposed if (Request == PlayerRequest.Next) { Request = PlayerRequest.Idle; if (!IterateIndex(Global.SoundCloud == null)) { if (State != PlayerState.Connected && State != PlayerState.Disconnected) { State = PlayerState.Connected; } Current = null; string cId = Channel.GetSettings().Language; if (cId != lId) { Language = Global.Languages.GetLanguage(cId); } lId = cId; await Channel.SendMessageAsync(Language.GetEntry("MusicHandler:FinishedPlaying")); } } else if (Request == PlayerRequest.Stop) { Request = PlayerRequest.Idle; State = PlayerState.Connected; Current = null; } if (State > PlayerState.Connected) { new Task(async() => await PlayAsync(Context, Channel, AvoidState: true)).Start(); } }