public override async Task <List <OnlinePlaylistEntry> > GetPlaylistEntries(OnlinePlaylist playlist) { var tracks = await getPlaylistEntries(playlist); return(tracks.Select((t) => { return new OnlinePlaylistEntry { OnlineSong = new OnlineSong(t.Title, t.NormalizedTitle) { Id = t.SongId, Artist = t.Artist, Album = t.Album, AlbumId = t.AlbumId, ArtistId = t.Artist, Disc = t.Disc, Genre = t.Genre, Rating = t.Rating, TrackCount = t.Track, Year = t.Year, TrackData = t, }, Id = t.PlaylistEntryId, PlaylistId = playlist.Id, SOrder = t.SOrder, SongId = t.SongId, }; }).ToList()); }
public async Task <bool> AddTemp(OnlinePlaylist playlist) { if (playlist.Entries == null || playlist.Entries.Count == 0) { playlist.Entries = await GetOnlineTracks(playlist); } return(await MusicProvider.AddTemp(playlist)); }
public async Task Play(OnlinePlaylistEntry entry, OnlinePlaylist playlist) { LogManager.Shared.LogPlayback(entry); using (new Spinner(Strings.LoadingPlaylist)) { await MusicManager.Shared.AddTemp(playlist); } var groupInfo = Database.Main.CreateGroupInfo(playlist); await PlayTempPlaylist(entry, groupInfo, playlist.Id); }
public async Task Play(OnlinePlaylistEntry entry, OnlinePlaylist playlist) { LogManager.Shared.LogPlayback(entry); using (new Spinner("Loading Playlist")) { await MusicManager.Shared.AddTemp(playlist); } var groupInfo = PlaylistSongViewModel.CreateGroupInfo(playlist); await PlayTempPlaylist(entry, groupInfo, playlist.Id); }
protected virtual void SearchInternal(OnlineContentSearchParameters searchParams, ManualResetEvent abortEvent) { this.Items.Clear(); this.SelectedItems.Clear(); if (searchParams.SearchText == "LookupMyPlaylists") { var playlists = OnlineContentSearcher.GetMyPlaylists(_searchType, abortEvent); if (playlists != null && playlists.Count > 0) { OnlinePlaylist p = null; MainThread.Send((c) => { SelectOnlinePlaylistDlg dlg = new SelectOnlinePlaylistDlg(playlists); if (dlg.ShowDialog(FindForm()) == DialogResult.OK) { p = dlg.SelectedItem; } }); if (p != null) { var results = OnlineContentSearcher.ExpandOnlinePlaylist(_searchType, p, abortEvent); if (results != null && results.Count > 0) { this.Items.AddRange(results); } } } } else { var results = OnlineContentSearcher.Search(_searchType, searchParams, abortEvent); if (results != null && results.Count > 0) { this.Items.AddRange(results); } } }
public async override Task <bool> AddToLibrary(OnlinePlaylist onlinePlaylist) { var tracks = await getPlaylistEntries(onlinePlaylist); if (!RequiresAuthentication) { var playlist = new Playlist(onlinePlaylist.Name) { ServiceId = Api.Identifier, ServiceType = ServiceType, Id = onlinePlaylist.Id, }; Database.Main.InsertOrReplace(playlist); //TODO: Decide what to do here. If you uncomment this line, all tracks show up in the library. Need to determine if you are adding the playlist or the songs. //await ProcessTracks(tracks.OfType<FullTrackData>().ToList()); await ProcessPlaylistTracks(tracks, new List <TempPlaylistEntry>()); await FinalizePlaylists(Id); return(true); } return(await AddToPlaylist(tracks.OfType <Track>().ToList(), onlinePlaylist.Name)); }
public async Task <List <PlaylistSong> > GetTracks(OnlinePlaylist playlist) { return(null); }
public async Task <bool> AddToLibrary(OnlinePlaylist playlist) { var api = ApiManager.Shared.GetMusicProvider(playlist.ServiceId); return(await api.AddToLibrary(playlist)); }
public async Task <List <OnlinePlaylistEntry> > GetOnlineTracks(OnlinePlaylist playlist) { var provider = ApiManager.Shared.GetMusicProvider(playlist.ServiceId); return(await provider.GetPlaylistEntries(playlist)); }
private void BindPlaylistNodesFromSelect( TreeNode playlistNode, OnlinePlaylist playlist, bool expand = true, bool showFetchedMessage = true, bool isDeleting = false) { if (tvUploads.InvokeRequired) { var d = new BindPlaylistNodesFromSelectDelegate(BindPlaylistNodesFromSelect); Invoke(d, new object[] { playlistNode, playlist, expand, showFetchedMessage, isDeleting }); } else { SetTreeViewEnabled(false); if (playlistNode != null) { var dbPlaylistEntry = MainForm.PlaylistFileRepo.LoadFromPlayListId(playlist.BrowseId).Result; playlistNode.Tag = new MusicManageTreeNodeModel { NodeType = MusicManageTreeNodeModel.NodeTypeEnum.Playlist, PlaylistTitle = playlist.Title, Duration = playlist.Duration, EntityOrBrowseId = playlist.BrowseId, CovertArtUrl = playlist.CoverArtUrl, SongTitleOrDescription = playlist.Description, DatabaseExistence = dbPlaylistEntry != null ? $"Exists ({dbPlaylistEntry.Id})" : "Not found or not mapped" }; var playlistItems = new List <TreeNode>(); foreach (var song in playlist.Songs) { var playlistItem = new TreeNode { Name = Guid.NewGuid().ToString(), Text = song.Title, Tag = Tag = new MusicManageTreeNodeModel { NodeType = MusicManageTreeNodeModel.NodeTypeEnum.PlaylistItem, ArtistTitle = song.ArtistTitle, AlbumTitle = song.AlbumTitle, CovertArtUrl = song.CoverArtUrl, Duration = song.Duration, SongTitleOrDescription = song.Title, MbId = "-", EntityOrBrowseId = song.VideoId, DatabaseExistence = "-", AltEntityId = song.SetVideoId, Uploaded = "-" } }; playlistItems.Add(playlistItem); } playlistNode.Nodes.AddRange(playlistItems.ToArray()); playlistNode.Text = playlistNode.Text + " (" + playlistNode.Nodes.Count + ")"; if (showFetchedMessage) { AppendUpdatesText($"Fetched {playlistItems.Count} playlist items.", ColourHelper.HexStringToColor("#0d5601")); } if (expand) { playlistNode.Expand(); } if (playlistNode.Checked) { CheckAllChildNodes(playlistNode, true); } if (!isDeleting) { SetMusicDetails((MusicManageTreeNodeModel)playlistNode.Tag); } } if (!isDeleting) { ShowPreloader(false); SetTreeViewEnabled(true); DisableAllActionButtons(false); } } }
public override Task <bool> AddToLibrary(OnlinePlaylist playlist) { throw new NotImplementedException(); }
/// <summary> /// HttpWebRequest POST request to send to YTM, which gets a playlist given a playlist or browse id /// (You can get this from the 'Requests.Playlists.GetPlaylists (plural)') request method. And then recurisvely /// fetches all tracks listed in the playlist /// </summary> /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param> /// <param name="browseId">Playlist id or browse id to retreive the playlist for</param> /// <param name="playlist">Shuuld be null initially. This object is used for recursive purposes</param> /// <param name="continuationToken">Should be null initially. This object is used for recursive purposes.</param> /// <returns>OnlinePlaylist object</returns> public static OnlinePlaylist GetPlaylist( string cookieValue, string browseId, OnlinePlaylist playlist = null, string continuationToken = null) { if (playlist == null) { playlist = new OnlinePlaylist(); } if (playlist.Songs == null) { playlist.Songs = new PlaylistSongCollection(); } try { var request = (HttpWebRequest)WebRequest.Create(Global.YTMusicBaseUrl + "browse" + (string.IsNullOrEmpty(continuationToken) ? "" : "?ctoken=" + continuationToken + "&continuation=" + continuationToken) + (string.IsNullOrEmpty(continuationToken) ? Global.YTMusicParams : Global.YTMusicParams.Replace('?', '&'))); request = AddStandardHeaders(request, cookieValue); request.ContentType = "application/json; charset=UTF-8"; request.Headers["X-Goog-AuthUser"] = "******"; request.Headers["x-origin"] = "https://music.youtube.com"; request.Headers["X-Goog-Visitor-Id"] = Global.GoogleVisitorId; request.Headers["Authorization"] = GetAuthorisation(GetSAPISIDFromCookie(cookieValue)); var context = JsonConvert.DeserializeObject <BrowseArtistRequestContext>( SafeFileStream.ReadAllText( Path.Combine( Global.WorkingDirectory, @"AppData\get_playlist_context.json"))); context.browseId = string.Format("{0}", browseId); byte[] postBytes = GetPostBytes(JsonConvert.SerializeObject(context)); request.ContentLength = postBytes.Length; using (var requestStream = request.GetRequestStream()) { requestStream.Write(postBytes, 0, postBytes.Length); requestStream.Close(); } postBytes = null; using (var response = (HttpWebResponse)request.GetResponse()) { string result; using (var brotli = new Brotli.BrotliStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress, true)) { var streamReader = new StreamReader(brotli); result = streamReader.ReadToEnd(); } if (string.IsNullOrEmpty(continuationToken)) { var playListData = JsonConvert.DeserializeObject <BrowsePlaylistResultsContext>(result); playlist.BrowseId = browseId; playlist.Title = playListData.header .musicEditablePlaylistDetailHeaderRenderer .header .musicDetailHeaderRenderer .title .runs[0] .text; playlist.Subtitle = playListData.header .musicEditablePlaylistDetailHeaderRenderer .header .musicDetailHeaderRenderer .subtitle.runs[0].text + playListData.header .musicEditablePlaylistDetailHeaderRenderer .header .musicDetailHeaderRenderer .subtitle.runs[1].text + playListData.header .musicEditablePlaylistDetailHeaderRenderer .header .musicDetailHeaderRenderer .subtitle.runs[2].text; playlist.Description = playListData.header .musicEditablePlaylistDetailHeaderRenderer .editHeader .musicPlaylistEditHeaderRenderer .description != null ? playListData.header .musicEditablePlaylistDetailHeaderRenderer .editHeader .musicPlaylistEditHeaderRenderer .description .runs[0] .text : ""; playlist.Duration = playListData.header .musicEditablePlaylistDetailHeaderRenderer .header .musicDetailHeaderRenderer .secondSubtitle .runs[2] .text; playlist.CoverArtUrl = playListData.header .musicEditablePlaylistDetailHeaderRenderer .header .musicDetailHeaderRenderer .thumbnail .croppedSquareThumbnailRenderer .thumbnail .thumbnails[0].url; try { playlist.PrivacyStatus = (OnlinePlaylist.PrivacyStatusEmum)Enum.Parse( typeof(OnlinePlaylist.PrivacyStatusEmum), playListData.header .musicEditablePlaylistDetailHeaderRenderer .editHeader .musicPlaylistEditHeaderRenderer .privacy, true); } catch { playlist.PrivacyStatus = OnlinePlaylist.PrivacyStatusEmum.Private; } playlist.Songs = GetInitalPlaylistSongs(playlist.Songs, result, out string continuation); if (!string.IsNullOrEmpty(continuation)) { return(GetPlaylist(cookieValue, browseId, playlist, continuation)); } } else { playlist.Songs = GetContinuationPlaylistSongs(playlist.Songs, result, out string continuation); if (!string.IsNullOrEmpty(continuation)) { return(GetPlaylist(cookieValue, browseId, playlist, continuation)); } } } } catch (Exception e) { var _ = e; #if DEBUG Console.Out.WriteLine("GetArtistSongs: " + e.Message); #endif } return(playlist); }
public override async Task <List <OnlinePlaylistEntry> > GetPlaylistEntries(OnlinePlaylist playlist) { App.ShowNotImplmented(); return(new List <OnlinePlaylistEntry>()); }
/// <summary> /// Execute the playlist management process /// </summary> public void Process(bool forceRefreshPlaylists = false) { Stopped = false; SetStatus("Processing playlist files", "Processing playlist files"); try { PlaylistFiles = MainForm.PlaylistFileRepo.LoadAll().Result; if (forceRefreshPlaylists) { Requests.ArtistCache.Playlists = Requests.Playlists.GetPlaylists(MainForm.Settings.AuthenticationCookie); } OnlinePlaylists = Requests.ArtistCache.Playlists; if (PlaylistFiles != null) { foreach (var playlistFile in PlaylistFiles) { ConnectionCheckWait(); if (MainFormAborting()) { return; } if (playlistFile.LastModifiedDate != playlistFile.LastUpload || (File.Exists(playlistFile.Path) && playlistFile.LastModifiedDate != new FileInfo(playlistFile.Path).LastWriteTime) || (playlistFile.PlaylistId != null && MatchOnlinePlaylist(playlistFile.PlaylistId, true) == null)) { try { if (MainFormAborting()) { return; } var updatedPlaylistFile = Providers.Playlist.PlaylistReader.ReadPlaylistFile(playlistFile.Path); playlistFile.Title = updatedPlaylistFile.Title; OnlinePlaylist onlinePlaylist = null; ConnectionCheckWait(); if (MainFormAborting()) { return; } if (!string.IsNullOrEmpty(playlistFile.PlaylistId) && MatchOnlinePlaylist(playlistFile.PlaylistId, true) != null) { onlinePlaylist = Requests.Playlists.GetPlaylist(MainForm.Settings.AuthenticationCookie, playlistFile.PlaylistId); } else { onlinePlaylist = MatchOnlinePlaylist(playlistFile.Title, false); if (onlinePlaylist != null) { // Get full playlist details onlinePlaylist = Requests.Playlists.GetPlaylist(MainForm.Settings.AuthenticationCookie, onlinePlaylist.BrowseId); playlistFile.PlaylistId = onlinePlaylist.BrowseId; } } if (MainFormAborting()) { return; } foreach (var playlistItem in updatedPlaylistFile.PlaylistItems) { if (MainFormAborting()) { return; } // We can only create or update a playlist if we have the YT Music video (entity) ID var musicFile = MainForm.MusicFileRepo.LoadFromPath(playlistItem.Path).Result; if (musicFile != null && !string.IsNullOrEmpty(musicFile.VideoId)) { var playlistToAdd = playlistItem; playlistItem.VideoId = musicFile.VideoId; playlistFile.PlaylistItems.Add(playlistToAdd); } else { // Check the file hash instead, in case the playlist file path is somehow different // to the watch folder file path (i.e. network folder locations or symbolics links) string hash = DirectoryHelper.GetFileHash(playlistItem.Path).Result; musicFile = MainForm.MusicFileRepo.LoadFromHash(hash).Result; if (musicFile != null && !string.IsNullOrEmpty(musicFile.VideoId)) { var playlistToAdd = playlistItem; playlistItem.VideoId = musicFile.VideoId; playlistFile.PlaylistItems.Add(playlistToAdd); } } } if (MainFormAborting()) { return; } if (onlinePlaylist != null) { HandleOnlinePlaylistPresent(onlinePlaylist, playlistFile); } else { HandleOnlinePlaylistNeedsCreating(playlistFile); } } catch (Exception e) { Logger.Log(e, $"PlaylistProcessor - Error processing playlist: {playlistFile.Title}"); } } } } } catch (Exception e) { if (e.Message.ToLower().Contains("thread was being aborted") || (e.InnerException != null && e.InnerException.Message.ToLower().Contains("thread was being aborted"))) { // Non-detrimental - Ignore to not clog up the application log // Logger.Log(e, "PlaylistProcessor", Log.LogTypeEnum.Warning); } else { Logger.Log(e, "Fatal error in PlaylistProcessor", Log.LogTypeEnum.Critical); } } Stopped = true; }
private void HandleOnlinePlaylistPresent(OnlinePlaylist onlinePlaylist, PlaylistFile playlistFile, bool forceRefreshPlaylists = false) { ConnectionCheckWait(); if (MainFormAborting()) { return; } if (onlinePlaylist.Songs != null && onlinePlaylist.Songs.Count < 5000) { foreach (var onlinePlaylistItem in onlinePlaylist.Songs) { if (playlistFile.PlaylistItems.Where(p => p.VideoId == onlinePlaylistItem.VideoId).Any()) { playlistFile.PlaylistItems.Remove(playlistFile.PlaylistItems.Where(p => p.VideoId == onlinePlaylistItem.VideoId).FirstOrDefault()); } } playlistFile.Description = onlinePlaylist.Description; playlistFile.Title = onlinePlaylist.Title; // Max YouTube Music playlist size if (onlinePlaylist.Songs.Count + playlistFile.PlaylistItems.Count > 5000) { for (int i = playlistFile.PlaylistItems.Count - 1; i >= 0; i--) { playlistFile.PlaylistItems.RemoveAt(i); if (onlinePlaylist.Songs.Count + playlistFile.PlaylistItems.Count > 5000) { break; } } } foreach (var playlistItem in playlistFile.PlaylistItems) { ConnectionCheckWait(); if (MainFormAborting()) { return; } for (int i = 0; i < 7; i++) { if (Requests.Playlists.AddPlaylistItem( MainForm.Settings.AuthenticationCookie, playlistFile.PlaylistId, playlistItem.VideoId, out var e)) { Logger.LogInfo("HandleOnlinePlaylistPresent", $"Adding item to online playlist: {playlistFile.Title}: Success"); break; } else { if (e.Message.Contains("404") && !forceRefreshPlaylists) { // Then playlist recently deleted. So create new one by running original 'Process()' Process(true); return; } else { if (i == 4) { Logger.Log(e, $"Error adding item to online playlist: {playlistFile.Title}", Log.LogTypeEnum.Error); break; } else { ThreadHelper.SafeSleep(3000); } } } } } } playlistFile.LastModifiedDate = new FileInfo(playlistFile.Path).LastWriteTime; playlistFile.LastUpload = playlistFile.LastModifiedDate; playlistFile.Save().Wait(); }
/// <summary> /// Execute the playlist management process /// </summary> public void Process(bool forceRefreshPlaylists = false) { while (MainForm.Paused) { ThreadHelper.SafeSleep(500); } Stopped = false; SetStatus("Processing playlist files", "Processing playlist files"); try { PlaylistFiles = MainForm.PlaylistFileRepo.LoadAll().Result; if (forceRefreshPlaylists) { Requests.ArtistCache.Playlists = Requests.Playlists.GetPlaylists(MainForm.Settings.AuthenticationCookie); } OnlinePlaylists = Requests.ArtistCache.Playlists; if (PlaylistFiles != null) { int index = 1; bool ytmPlaylistCreationLimitReached = false; foreach (var playlistFile in PlaylistFiles) { ProcessingPlaylistsFinished = false; ConnectionCheckWait(); while (MainForm.Paused) { ThreadHelper.SafeSleep(500); } SetStatus($"Checking playlist file ({index}/{PlaylistFiles.Count})", $"Checking playlist file ({index}/{PlaylistFiles.Count})"); MainForm.SetProcessingPlaylistMessage( playlistFile.Path, string.IsNullOrEmpty(playlistFile.Title) ? Path.GetFileNameWithoutExtension(playlistFile.Path) : playlistFile.Title, GetProcessingPlaylistTootipText(playlistFile)); if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } if (playlistFile.LastModifiedDate != playlistFile.LastUpload || (File.Exists(playlistFile.Path) && playlistFile.LastModifiedDate != new FileInfo(playlistFile.Path).LastWriteTime) || (playlistFile.PlaylistId != null && MatchOnlinePlaylist(playlistFile.PlaylistId, true) == null)) { try { if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } if (!MainForm.Settings.UploadPlaylists) { return; } var updatedPlaylistFile = Providers.Playlist.PlaylistReader.ReadPlaylistFile(playlistFile.Path); playlistFile.Title = updatedPlaylistFile.Title; OnlinePlaylist onlinePlaylist = null; MainForm.SetProcessingPlaylistMessage( playlistFile.Path, string.IsNullOrEmpty(playlistFile.Title) ? Path.GetFileNameWithoutExtension(playlistFile.Path) : playlistFile.Title, GetProcessingPlaylistTootipText(playlistFile)); ConnectionCheckWait(); if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } if (!string.IsNullOrEmpty(playlistFile.PlaylistId) && MatchOnlinePlaylist(playlistFile.PlaylistId, true) != null) { try { onlinePlaylist = Requests.Playlists.GetPlaylist(MainForm.Settings.AuthenticationCookie, playlistFile.PlaylistId); } catch { } } else { try { onlinePlaylist = MatchOnlinePlaylist(playlistFile.Title, false); } catch { } if (onlinePlaylist != null && onlinePlaylist.BrowseId != null) { // Get full playlist details try { onlinePlaylist = Requests.Playlists.GetPlaylist(MainForm.Settings.AuthenticationCookie, onlinePlaylist.BrowseId); playlistFile.PlaylistId = onlinePlaylist.BrowseId; } catch { } } } if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } if (updatedPlaylistFile != null && updatedPlaylistFile.PlaylistItems != null && updatedPlaylistFile.PlaylistItems.Count > 0) { updatedPlaylistFile.PlaylistItems.AsParallel().ForAllInApproximateOrder(playlistItem => { while (MainForm.Paused) { ThreadHelper.SafeSleep(500); } if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } // We can only create or update a playlist if we have the YT Music video (entity) ID MusicFile musicFile = null; musicFile = MainForm.MusicFileRepo.LoadFromPath(playlistItem.Path).Result; if (musicFile != null && string.IsNullOrEmpty(musicFile.VideoId)) { string entityId = string.Empty; ConnectionCheckWait(); if (Requests.IsSongUploaded(musicFile.Path, MainForm.Settings.AuthenticationCookie, ref entityId, out string videoId, MainForm.MusicDataFetcher, false) != Requests.UploadCheckResult.NotPresent) { musicFile.VideoId = videoId; musicFile.Save().Wait(); } } if (musicFile != null && !string.IsNullOrEmpty(musicFile.VideoId)) { var playlistToAdd = playlistItem; playlistItem.VideoId = musicFile.VideoId; playlistFile.PlaylistItems.Add(playlistToAdd); } else { // Check the file hash instead, in case the playlist file path is somehow different // to the watch folder file path (i.e. network folder locations or symbolics links) string hash = DirectoryHelper.GetFileHash(playlistItem.Path).Result; if (hash != null) { musicFile = MainForm.MusicFileRepo.LoadFromHash(hash).Result; if (musicFile != null && string.IsNullOrEmpty(musicFile.VideoId)) { string entityId = string.Empty; ConnectionCheckWait(); if (Requests.IsSongUploaded(musicFile.Path, MainForm.Settings.AuthenticationCookie, ref entityId, out string videoId, MainForm.MusicDataFetcher, false) != Requests.UploadCheckResult.NotPresent) { musicFile.VideoId = videoId; musicFile.Save().Wait(); } } if (musicFile != null && !string.IsNullOrEmpty(musicFile.VideoId)) { var playlistToAdd = playlistItem; playlistItem.VideoId = musicFile.VideoId; playlistFile.PlaylistItems.Add(playlistToAdd); } } } }, Global.MaxDegreesOfParallelism); } if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } if (onlinePlaylist != null) { HandleOnlinePlaylistPresent( onlinePlaylist, playlistFile, index, PlaylistFiles.Count, out ytmPlaylistCreationLimitReached); } else { int currentSessionPlaylistUploadCount = MainForm.Settings.CurrentSessionPlaylistUploadCount ?? 0; if (currentSessionPlaylistUploadCount <= Global.MaxNewPlaylistsPerSession) { HandleOnlinePlaylistNeedsCreating( playlistFile, index, PlaylistFiles.Count, out ytmPlaylistCreationLimitReached); } else { ytmPlaylistCreationLimitReached = true; } } } catch (Exception e) { if (e.Message.Contains("Empty Playlist")) { // Ignore - don't create playlist Logger.LogWarning( "Playlist Processor", "Empty playlist detected. It will be ignored: " + playlistFile.Path); playlistFile.LastModifiedDate = new FileInfo(playlistFile.Path).LastWriteTime; playlistFile.LastUpload = playlistFile.LastModifiedDate; playlistFile.Save().Wait(); } else if (e.Message.Contains("Could not find the file")) { // Ignore -It's probably been moved / deleted playlistFile.Delete().Wait(); } else { Logger.Log(e, $"PlaylistProcessor - Error processing playlist: {playlistFile.Title}"); } } } if (ytmPlaylistCreationLimitReached) { SetStatus($"YTM playlist creation limited reached - Stopping playlist processing for this session.", $"YTM playlist creation limited reached"); MainForm.Settings.CurrentSessionPlaylistUploadCount = 0; MainForm.Settings.LastPlaylistUpload = DateTime.Now; MainForm.Settings.Save().Wait(); Logger.LogInfo( "PlaylistProcessor.Process", "YTM playlist creation limited reached - Stopping playlist processing for this session."); ThreadHelper.SafeSleep(15000); break; } if (index == PlaylistFiles.Count) { ProcessingPlaylistsFinished = true; } index++; } } } catch (Exception e) { Logger.Log(e, "Fatal error in PlaylistProcessor", Log.LogTypeEnum.Critical); } Stopped = true; }
private void HandleOnlinePlaylistPresent( OnlinePlaylist onlinePlaylist, PlaylistFile playlistFile, int currentPlaylistIndex, int totalPlaylists, out bool limitedReached, bool forceRefreshPlaylists = false) { limitedReached = false; ConnectionCheckWait(); if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } if (onlinePlaylist.Songs != null && onlinePlaylist.Songs.Count < 5000) { foreach (var onlinePlaylistItem in onlinePlaylist.Songs) { if (playlistFile.PlaylistItems.Where(p => p.VideoId == onlinePlaylistItem.VideoId).Any()) { playlistFile.PlaylistItems.Remove(playlistFile.PlaylistItems.Where(p => p.VideoId == onlinePlaylistItem.VideoId).FirstOrDefault()); } } playlistFile.Description = onlinePlaylist.Description; playlistFile.Title = onlinePlaylist.Title; // Max YouTube Music playlist size if (onlinePlaylist.Songs.Count + playlistFile.PlaylistItems.Count > 5000) { for (int i = playlistFile.PlaylistItems.Count - 1; i >= 0; i--) { playlistFile.PlaylistItems.RemoveAt(i); if (onlinePlaylist.Songs.Count + playlistFile.PlaylistItems.Count > 5000) { break; } } } int index = 1; foreach (var playlistItem in playlistFile.PlaylistItems) { ConnectionCheckWait(); if (MainFormAborting() || !MainForm.Settings.UploadPlaylists) { return; } SetStatus($"Processing playlist file {currentPlaylistIndex}/{totalPlaylists}: Adding track to existing {index}/{playlistFile.PlaylistItems.Count}", $"Processing playlist file {currentPlaylistIndex}/{totalPlaylists}"); while (MainForm.Paused) { ThreadHelper.SafeSleep(500); } for (int i = 0; i < 2; i++) { MainForm.SetProcessingPlaylistMessage( playlistFile.Path, string.IsNullOrEmpty(playlistFile.Title) ? Path.GetFileNameWithoutExtension(playlistFile.Path) : playlistFile.Title, GetProcessingPlaylistTootipText(playlistFile)); if (Requests.Playlists.AddPlaylistItem( MainForm.Settings.AuthenticationCookie, playlistFile.PlaylistId, playlistItem.VideoId, out var e)) { Logger.LogInfo("HandleOnlinePlaylistPresent", $"Adding item to online playlist: {playlistFile.Title}: Success"); ThreadHelper.SafeSleep(Global.PlaylistAddWait); break; } else { if (e.Message.Contains("404") && !forceRefreshPlaylists) { // Then playlist recently deleted. So create new one by running original 'Process()' Process(true); return; } else { if (i == 1) { limitedReached = true; Logger.Log(e, $"Error adding item to online playlist: {playlistFile.Title}", Log.LogTypeEnum.Error); break; } else { ThreadHelper.SafeSleep(3000); } } } if (limitedReached) { break; } } index++; } } playlistFile.LastModifiedDate = new FileInfo(playlistFile.Path).LastWriteTime; playlistFile.LastUpload = playlistFile.LastModifiedDate; playlistFile.Save().Wait(); }
public override async Task <bool> AddToLibrary(OnlinePlaylist playlist) { App.ShowNotImplmented(); return(false); }
public async override Task <bool> AddToLibrary(OnlinePlaylist onlinePlaylist) { var tracks = await getPlaylistEntries(onlinePlaylist); return(await AddToPlaylist(tracks.OfType <Track>().ToList(), onlinePlaylist.Name)); }
public override Task <List <OnlinePlaylistEntry> > GetPlaylistEntries(OnlinePlaylist playlist) { throw new NotImplementedException(); }
/// <summary> /// HttpWebRequest POST request to send to YTM which fetches a list (collection) of Playlists (without playlist tracks). /// Use the 'Requests.Playlists.GetPlaylist (singular)' method to get an individual playlist complete with track listing. /// </summary> /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param> /// <returns>OnlinePlaylistCollection object (list of playlists without tracks)</returns> public static OnlinePlaylistCollection GetPlaylists( string cookieValue, string continuationToken = null, OnlinePlaylistCollection playListCol = null) { if (playListCol == null) { playListCol = new OnlinePlaylistCollection(); } try { var request = (HttpWebRequest)WebRequest.Create(Global.YTMusicBaseUrl + "browse" + (string.IsNullOrEmpty(continuationToken) ? "" : "?ctoken=" + continuationToken + "&continuation=" + continuationToken) + (string.IsNullOrEmpty(continuationToken) ? Global.YTMusicParams : Global.YTMusicParams.Replace('?', '&'))); request = AddStandardHeaders(request, cookieValue); request.ContentType = "application/json; charset=UTF-8"; request.Headers["X-Goog-AuthUser"] = "******"; request.Headers["x-origin"] = "https://music.youtube.com"; request.Headers["X-Goog-Visitor-Id"] = Global.GoogleVisitorId; request.Headers["Authorization"] = GetAuthorisation(GetSAPISIDFromCookie(cookieValue)); byte[] postBytes = GetPostBytes( SafeFileStream.ReadAllText( Path.Combine(Global.WorkingDirectory, @"AppData\get_playlists_context.json"))); request.ContentLength = postBytes.Length; using (var requestStream = request.GetRequestStream()) { requestStream.Write(postBytes, 0, postBytes.Length); requestStream.Close(); } postBytes = null; using (var response = (HttpWebResponse)request.GetResponse()) { string result; using (var brotli = new Brotli.BrotliStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress, true)) { var streamReader = new StreamReader(brotli); result = streamReader.ReadToEnd(); if (string.IsNullOrEmpty(continuationToken)) { var playListsResultContext = JsonConvert.DeserializeObject <BrowsePlaylistsResultsContext>(result); var playListResults = playListsResultContext.contents .singleColumnBrowseResultsRenderer .tabs[0] .tabRenderer .content .sectionListRenderer .contents[1] .itemSectionRenderer .contents[0] .gridRenderer .items; foreach (var item in playListResults) { if (item.musicTwoRowItemRenderer.title.runs[0].text != "New playlist" && item.musicTwoRowItemRenderer.title.runs[0].text != "Your likes") { try { var pl = new OnlinePlaylist { Title = item.musicTwoRowItemRenderer.title.runs[0].text }; try { pl.Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text + item.musicTwoRowItemRenderer.subtitle.runs[1].text + item.musicTwoRowItemRenderer.subtitle.runs[2].text; } catch { try { pl.Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text + item.musicTwoRowItemRenderer.subtitle.runs[1].text; } catch { try { pl.Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text; } catch { } } } pl.BrowseId = item.musicTwoRowItemRenderer.navigationEndpoint.browseEndpoint.browseId; try { pl.CoverArtUrl = item.musicTwoRowItemRenderer.thumbnailRenderer.musicThumbnailRenderer.thumbnail.thumbnails[0].url; } catch { } playListCol.Add(pl); } catch { } } } string continuation = string.Empty; var jo = JObject.Parse(result); var musicShelfRendererTokens = jo.Descendants().Where(t => t.Type == JTokenType.Property && ((JProperty)t).Name == "itemSectionRenderer") .Select(p => ((JProperty)p).Value) .ToList(); foreach (var token in musicShelfRendererTokens) { Console.Out.WriteLine(token); var msr = token.ToObject <BrowsePlaylistsResultsContext.Itemsectionrenderer>(); if (msr != null && msr.contents[0].gridRenderer.continuations != null && msr.contents[0].gridRenderer.continuations.Length > 0 && msr.contents[0].gridRenderer.continuations[0].nextContinuationData != null && msr.contents[0].gridRenderer.continuations[0].nextContinuationData.continuation != null) { continuation = msr.contents[0].gridRenderer.continuations[0].nextContinuationData.continuation; } } if (!string.IsNullOrEmpty(continuation)) { return(GetPlaylists(cookieValue, continuation, playListCol)); } } else { var playListsResultContext = JsonConvert.DeserializeObject <BrowsePlaylistsResultsContinuationContext>(result); var playListResults = playListsResultContext.continuationContents .gridContinuation .items; foreach (var item in playListResults) { if (item.musicTwoRowItemRenderer.title.runs[0].text != "New playlist" && item.musicTwoRowItemRenderer.title.runs[0].text != "Your likes") { try { var pl = new OnlinePlaylist { Title = item.musicTwoRowItemRenderer.title.runs[0].text }; try { pl.Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text + item.musicTwoRowItemRenderer.subtitle.runs[1].text + item.musicTwoRowItemRenderer.subtitle.runs[2].text; } catch { try { pl.Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text + item.musicTwoRowItemRenderer.subtitle.runs[1].text; } catch { try { pl.Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text; } catch { } } } pl.BrowseId = item.musicTwoRowItemRenderer.navigationEndpoint.browseEndpoint.browseId; try { pl.CoverArtUrl = item.musicTwoRowItemRenderer.thumbnailRenderer.musicThumbnailRenderer.thumbnail.thumbnails[0].url; } catch { } playListCol.Add(pl); } catch (Exception e) { Logger.Log(e, "GetPlaylists - Error fetching a playlist", Log.LogTypeEnum.Error); } } } string continuation = string.Empty; var jo = JObject.Parse(result); var musicShelfRendererTokens = jo.Descendants().Where(t => t.Type == JTokenType.Property && ((JProperty)t).Name == "continuationContents") .Select(p => ((JProperty)p).Value) .ToList(); foreach (var token in musicShelfRendererTokens) { Console.Out.WriteLine(token); var msr = token.ToObject <BrowsePlaylistsResultsContinuationContext.Continuationcontents>(); if (msr != null && msr.gridContinuation != null && msr.gridContinuation.continuations != null && msr.gridContinuation.continuations.Length > 0 && msr.gridContinuation.continuations[0].nextContinuationData != null && msr.gridContinuation.continuations[0].nextContinuationData.continuation != null) { continuation = msr.gridContinuation.continuations[0].nextContinuationData.continuation; } } if (!string.IsNullOrEmpty(continuation)) { return(GetPlaylists(cookieValue, continuation, playListCol)); } } } } } catch (Exception e) { var _ = e; #if DEBUG Console.Out.WriteLine("GetPlaylists: " + e.Message); #endif } return(playListCol); }