Example #1
0
        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());
        }
Example #2
0
        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));
        }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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));
        }
Example #7
0
 public async Task <List <PlaylistSong> > GetTracks(OnlinePlaylist playlist)
 {
     return(null);
 }
Example #8
0
        public async Task <bool> AddToLibrary(OnlinePlaylist playlist)
        {
            var api = ApiManager.Shared.GetMusicProvider(playlist.ServiceId);

            return(await api.AddToLibrary(playlist));
        }
Example #9
0
        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);
                }
            }
        }
Example #11
0
 public override Task <bool> AddToLibrary(OnlinePlaylist playlist)
 {
     throw new NotImplementedException();
 }
Example #12
0
            /// <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);
            }
Example #13
0
 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();
        }
Example #18
0
 public override async Task <bool> AddToLibrary(OnlinePlaylist playlist)
 {
     App.ShowNotImplmented();
     return(false);
 }
Example #19
0
        public async override Task <bool> AddToLibrary(OnlinePlaylist onlinePlaylist)
        {
            var tracks = await getPlaylistEntries(onlinePlaylist);

            return(await AddToPlaylist(tracks.OfType <Track>().ToList(), onlinePlaylist.Name));
        }
Example #20
0
 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);
            }