/// <inheritdoc/>
        protected override async Task BaseDecompressAsync(Stream inputStream, Stream outputStream, CancellationToken cancellationToken = default)
        {
            using var brotliStream = new Brotli.BrotliStream(inputStream, CompressionMode.Decompress, true);
            await brotliStream.CopyToAsync(outputStream, DefaultBufferSize, cancellationToken).ConfigureAwait(false);

            await outputStream.FlushAsync(cancellationToken).ConfigureAwait(false);
            await brotliStream.FlushAsync(cancellationToken).ConfigureAwait(false);
        }
        /// <inheritdoc/>
        protected override void BaseDecompress(Stream inputStream, Stream outputStream)
        {
            using var brotliStream = new Brotli.BrotliStream(inputStream, CompressionMode.Decompress, true);
            brotliStream.CopyTo(outputStream);

            outputStream.Flush();
            brotliStream.Flush();
        }
        /// <inheritdoc/>
        protected override void BaseCompress(Stream inputStream, Stream outputStream)
        {
            using var brotliStream = new Brotli.BrotliStream(outputStream, CompressionMode.Compress, true);
            brotliStream.SetQuality(Quality);
            brotliStream.SetWindow(Window);
            inputStream.CopyTo(brotliStream);

            inputStream.Flush();
            brotliStream.Flush();
        }
Exemple #4
0
 public void MemoryStreamShouldBeDecodable()
 {
     memoryStream.Position = 0;
     using (var bs = new BrotliStream(memoryStream, CompressionMode.Decompress))
         using (var msOutput = new MemoryStream())
         {
             bs.CopyTo(msOutput);
             msOutput.Seek(0, SeekOrigin.Begin);
             var output = msOutput.ToArray();
             Encoding.UTF8.GetString(output).ShouldEqual("onetwothree");
         }
 }
        /// <inheritdoc/>
        protected override async Task BaseCompressAsync(Stream inputStream, Stream outputStream, CancellationToken cancellationToken = default)
        {
            using (var brotliStream = new Brotli.BrotliStream(outputStream, CompressionMode.Compress))
            {
                brotliStream.SetQuality(Quality);
                brotliStream.SetWindow(Window);
                await inputStream.CopyToAsync(brotliStream, DefaultBufferSize, cancellationToken).ConfigureAwait(false);

                await inputStream.FlushAsync(cancellationToken).ConfigureAwait(false);

                await brotliStream.FlushAsync(cancellationToken).ConfigureAwait(false);
            }
        }
        /// <inheritdoc/>
        protected override byte[] BaseDecompress(byte[] compressedBytes)
        {
            using var inputStream = new MemoryStream(compressedBytes);
            using var outputStream = new MemoryStream();
            using (var brotliStream = new Brotli.BrotliStream(inputStream, CompressionMode.Decompress))
            {
                brotliStream.CopyTo(outputStream, compressedBytes.Length);

                outputStream.Flush();
                brotliStream.Flush();
            }
            return outputStream.ToArray();
        }
Exemple #7
0
        /// <summary>
        /// HttpWebRequest POST request to send to YouTube to check if the user's is authenticated (signed in) by determining
        /// if a generic request is successful given the current authentication cookie value we have stored.        ///
        /// In this case, we're actually perform a request for personally uploaded music files
        /// </summary>
        /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param>
        /// <returns>True if successfully authenticated, false otherwise</returns>
        public static bool IsAuthenticated(string cookieValue)
        {
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(Global.YTMusicBaseUrl + "browse" + Global.YTMusicParams);
                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\check_auth_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();
                    }

                    object json = JsonConvert.DeserializeObject(result);
                }
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine(ex.Message);

                return(false);
            }

            return(true);
        }
        /// <inheritdoc/>
        protected override byte[] BaseCompress(byte[] bytes)
        {
            using var inputStream = new MemoryStream(bytes);
            using var outputStream = new MemoryStream();
            using (var brotliStream = new Brotli.BrotliStream(outputStream, CompressionMode.Compress))
            {
                brotliStream.SetQuality(Quality);
                brotliStream.SetWindow(Window);
                inputStream.CopyTo(brotliStream, bytes.Length);
                //inputStream.WriteTo(brotliStream);
                //brotliStream.Write(bytes, 0, bytes.Length);

                inputStream.Flush();
                brotliStream.Flush();
            }
            return outputStream.ToArray();
        }
Exemple #9
0
            /// <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)
            {
                var playListCol = new OnlinePlaylistCollection();

                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(Global.YTMusicBaseUrl +
                                                                    "browse?" + Global.YTMusicParams);

                    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();

                            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
                                    {
                                        playListCol.Add(new OnlinePlaylist
                                        {
                                            Title    = item.musicTwoRowItemRenderer.title.runs[0].text,
                                            Subtitle = item.musicTwoRowItemRenderer.subtitle.runs[0].text +
                                                       item.musicTwoRowItemRenderer.subtitle.runs[1].text +
                                                       item.musicTwoRowItemRenderer.subtitle.runs[2].text,
                                            BrowseId    = item.musicTwoRowItemRenderer.navigationEndpoint.browseEndpoint.browseId,
                                            CoverArtUrl = item.musicTwoRowItemRenderer.thumbnailRenderer.musicThumbnailRenderer.thumbnail.thumbnails[0].url
                                        });
                                    }
                                    catch (Exception e)
                                    {
                                        Logger.Log(e, "GetPlaylists - Error fetching a playlist", Log.LogTypeEnum.Error);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    var _ = e;
#if DEBUG
                    Console.Out.WriteLine("GetPlaylists: " + e.Message);
#endif
                }

                return(playListCol);
            }
        /// <summary>
        /// HttpWebRequest POST request - Recursively fetches all the songs of an artist from YouTube Music's 'Upload' section
        /// </summary>
        /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param>
        /// <param name="browseId">YouTube Music's navigation ID for an individual artist, retreived from 'GetArtists' request</param>
        /// <param name="songs">Input ArtistCache 'Songs' object (should be empty when initialising - this is a recursive method)</param>
        /// <param name="continuationToken">Token from YouTube Music indicated more results to fetch, and the token to get them
        /// (shoult be empty when initialising - this is a recursive method)</param>
        /// <returns>ArtistCache object</returns>
        public static AlbumSongCollection GetArtistSongs(
            string cookieValue,
            string browseId,
            AlbumSongCollection albumSongCollection = null,
            string continuationToken = null)
        {
            if (albumSongCollection == null)
            {
                albumSongCollection = new AlbumSongCollection();
            }

            if (albumSongCollection.Songs == null)
            {
                albumSongCollection.Songs = new SongCollection();
            }

            if (albumSongCollection.Albums == null)
            {
                albumSongCollection.Albums = new AlbumCollection();
            }

            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_artist_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))
                    {
                        albumSongCollection = GetInitalArtistSongs(albumSongCollection, result, out string continuation);
                        if (!string.IsNullOrEmpty(continuation))
                        {
                            return(GetArtistSongs(cookieValue, browseId, albumSongCollection, continuation));
                        }
                    }
                    else
                    {
                        albumSongCollection = GetContinuationArtistSongs(albumSongCollection, result, out string continuation);
                        if (!string.IsNullOrEmpty(continuation))
                        {
                            return(GetArtistSongs(cookieValue, browseId, albumSongCollection, continuation));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                var _ = e;
#if DEBUG
                Console.Out.WriteLine("GetArtistSongs: " + e.Message);
#endif
            }

            return(albumSongCollection);
        }
Exemple #11
0
            /// <summary>
            /// HttpWebRequest POST request to send to add a playlist item (track) to an existing YouTube Music playlist
            /// </summary>
            /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param>
            /// <param name="playlistId">YT Music playlistid (or browseId) to add to</param>
            /// <param name="videoId">This is the unique track id to add</param>
            /// <returns>True if successfully, false otherwise</returns>
            public static bool AddPlaylistItem(string cookieValue, string playlistId, string videoId, out Exception ex)
            {
                ex = null;
                string originalRequest = string.Empty;

                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(
                        Global.YTMusicBaseUrl +
                        "browse/edit_playlist" +
                        Global.YTMusicParams);

                    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 <AddPlaylistItemContext>(
                        SafeFileStream.ReadAllText(
                            Path.Combine(
                                Global.WorkingDirectory,
                                @"AppData\add_playlist_item_context.json")));

                    if (playlistId.StartsWith("VL"))
                    {
                        playlistId = playlistId.Substring(2, playlistId.Length - 2);
                    }

                    context.playlistId = playlistId;
                    context.actions[0].addedVideoId = videoId;

                    var    delta           = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now);
                    double utcMinuteOffset = delta.TotalMinutes;
                    context.context.client.utcOffsetMinutes = (int)utcMinuteOffset;

                    byte[] postBytes = GetPostBytes(JsonConvert.SerializeObject(context));

                    try
                    {
                        originalRequest = JsonConvert.SerializeObject(context);
                    }
                    catch { }

                    request.ContentLength = postBytes.Length;
                    using (var requestStream = request.GetRequestStream())
                    {
                        requestStream.Write(postBytes, 0, postBytes.Length);
                        requestStream.Close();
                    }

                    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 (result.ToLower().Contains("error"))
                        {
                            throw new Exception("Error: " + result);
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.LogError("AddPlaylistItem", "Error adding to playlist: " + playlistId, false, originalRequest);
                    ex = e;
                    return(false);
                }

                return(true);
            }
Exemple #12
0
        private async Task ReceiveMessageLoop()
        {
            try
            {
                var stableBuffer = new byte[16];
                var buffer       = new byte[4096];
                while (this.Connected)
                {
                    await NetStream.ReadBAsync(stableBuffer, 0, 16);

                    var protocol = DanmakuProtocol.FromBuffer(stableBuffer);
                    if (protocol.PacketLength < 16)
                    {
                        throw new NotSupportedException("协议失败: (L:" + protocol.PacketLength + ")");
                    }
                    var payloadlength = protocol.PacketLength - 16;
                    if (payloadlength == 0)
                    {
                        continue; // 没有内容了
                    }

                    buffer = new byte[payloadlength];

                    await NetStream.ReadBAsync(buffer, 0, payloadlength);

                    if (protocol.Version == 2 && protocol.Action == 5)                  // 处理deflate消息
                    {
                        using (var ms = new MemoryStream(buffer, 2, payloadlength - 2)) // Skip 0x78 0xDA
                            using (var deflate = new DeflateStream(ms, CompressionMode.Decompress))
                            {
                                var headerbuffer = new byte[16];
                                try
                                {
                                    while (true)
                                    {
                                        await deflate.ReadBAsync(headerbuffer, 0, 16);

                                        var protocol_in = DanmakuProtocol.FromBuffer(headerbuffer);
                                        payloadlength = protocol_in.PacketLength - 16;
                                        var danmakubuffer = new byte[payloadlength];
                                        await deflate.ReadBAsync(danmakubuffer, 0, payloadlength);

                                        ProcessDanmaku(protocol.Action, danmakubuffer);
                                    }
                                }
                                catch (Exception e)
                                {
                                }
                            }
                    }
                    else if (protocol.Version == 3 && protocol.Action == 5) // brotli?
                    {
                        using (var ms = new MemoryStream(buffer))           // Skip 0x78 0xDA
                            using (var deflate = new Brotli.BrotliStream(ms, CompressionMode.Decompress))
                            {
                                var headerbuffer = new byte[16];
                                try
                                {
                                    while (true)
                                    {
                                        await deflate.ReadBAsync(headerbuffer, 0, 16);

                                        var protocol_in = DanmakuProtocol.FromBuffer(headerbuffer);
                                        payloadlength = protocol_in.PacketLength - 16;
                                        var danmakubuffer = new byte[payloadlength];
                                        await deflate.ReadBAsync(danmakubuffer, 0, payloadlength);

                                        ProcessDanmaku(protocol.Action, danmakubuffer);
                                    }
                                }
                                catch (Exception e)
                                {
                                }
                            }
                    }
                    else
                    {
                        ProcessDanmaku(protocol.Action, buffer);
                    }
                }
            }
            //catch (NotSupportedException ex)
            //{
            //    this.Error = ex;
            //    _disconnect();
            //}
            catch (Exception ex)
            {
                this.Error = ex;
                _disconnect();
            }
        }
Exemple #13
0
            /// <summary>
            /// HttpWebRequest POST request to send to YTM to create a new playlist
            /// </summary>
            /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param>
            /// <param name="title">Title to call the playlist</param>
            /// <param name="description">Description of the playlist (does not allow HTML tags)</param>
            /// <param name="videoIds">List of video ids (track ids) to create the playlist with</param>
            /// <param name="privacyStatus">PRIVATE, PUBLIC or UNLISTED - Default it PUBLIC</param>
            /// <param name="playlistId">(Output) playlist id once created</param>
            /// <param name="browseId">(Output) browse id once create (It's just the playlist ID prefixed with 'VL')</param>
            /// <param name="errorMessage">(Output)Any error message encountered during the request</param>
            /// <returns>True if request is successful, false otherwise</returns>
            public static bool CreatePlaylist(
                string cookieValue,
                string title,
                string description,
                List <string> videoIds,
                PrivacyStatusEmum privacyStatus,
                out string playlistId,
                out string browseId,
                out Exception ex)
            {
                ex = null;
                string originalRequest = string.Empty;

                browseId   = string.Empty;
                playlistId = string.Empty;

                if (description == null)
                {
                    description = string.Empty;
                }

                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(
                        Global.YTMusicBaseUrl +
                        "playlist/create" +
                        Global.YTMusicParams);

                    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 <CreatePlaylistRequestContext>(
                        SafeFileStream.ReadAllText(
                            Path.Combine(
                                Global.WorkingDirectory,
                                @"AppData\create_playlist_context.json")));

                    context.title         = title;
                    context.description   = description;
                    context.privacyStatus = privacyStatus.ToString().ToUpper();
                    context.videoIds      = videoIds.ToArray();

                    var    delta           = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now);
                    double utcMinuteOffset = delta.TotalMinutes;
                    context.context.client.utcOffsetMinutes = (int)utcMinuteOffset;

                    try
                    {
                        originalRequest = JsonConvert.SerializeObject(context);
                    }
                    catch { }

                    byte[] postBytes = GetPostBytes(JsonConvert.SerializeObject(context));
                    request.ContentLength = postBytes.Length;

                    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 (result.ToLower().Contains("error"))
                        {
                            throw new Exception("Error: " + result + ": Original Http Request: " + originalRequest);
                        }
                        else
                        {
                            var runObject = JObject.Parse(result);
                            var browseIds = runObject.Descendants()
                                            .Where(t => t.Type == JTokenType.Property && ((JProperty)t).Name == "browseId")
                                            .Select(p => ((JProperty)p).Value).ToList();

                            if (browseIds.Count > 0)
                            {
                                browseId = browseIds[0].ToString();
                            }

                            var playlistIds = runObject.Descendants()
                                              .Where(t => t.Type == JTokenType.Property && ((JProperty)t).Name == "playlistId")
                                              .Select(p => ((JProperty)p).Value).ToList();

                            if (playlistIds.Count > 0)
                            {
                                playlistId = playlistIds[0].ToString();
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Logger.LogError("CreatePlaylist", "Error creating playlist: " + title, originalRequest);
                    ex = e;
                    return(false);
                }

                return(true);
            }
Exemple #14
0
        /// <summary>
        /// HttpWebRequest POST request to send to YouTube delete a YT music track fro the users uploads
        /// </summary>
        /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param>
        /// <param name="entityId">YT Music entity ID to delete</param>
        /// <returns>True if successfully authenticated, false otherwise</returns>
        public static bool DeleteAlbumOrTrackFromYTMusic(string cookieValue, string entityId, out string errorMessage)
        {
            errorMessage = string.Empty;

            try
            {
                var request = (HttpWebRequest)WebRequest.Create(
                    Global.YouTubeMusicBaseUrl +
                    "music/delete_privately_owned_entity" +
                    Global.YouTubeMusicParams);

                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 <DeleteFromYTMusicRequestContext>(
                    SafeFileStream.ReadAllText(
                        Path.Combine(
                            Global.WorkingDirectory,
                            @"AppData\delete_song_context.json")));

                context.entityId = entityId;
                byte[] postBytes = GetPostBytes(JsonConvert.SerializeObject(context));
                request.ContentLength = postBytes.Length;

                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 (result.ToLower().Contains("error"))
                    {
                        errorMessage = "Error: " + result;
                        return(false);
                    }
                }
            }
            catch (Exception e)
            {
                errorMessage = "Error: " + e.Message;
                return(false);
            }

            return(true);
        }
Exemple #15
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);
            }
            /// <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);
            }
Exemple #17
0
            /// <summary>
            /// HttpWebRequest POST request to send to YTM to remove a playlist item (track) from an existing playlist
            /// </summary>
            /// <param name="cookieValue">Cookie from a previous YouTube Music sign in via this application (stored in the database)</param>
            /// <param name="playlistId">Playlist id to remove a track from</param>
            /// <param name="videoEntityId">VideoId (unique track entityId) of the track to remove</param>
            /// <param name="setVideoEntityId">SetVideoId (alt unbique track entityId) of the track to remove</param>
            /// <param name="errorMessage">(Output) Error message if error encountered while sending the request</param>
            /// <returns>True if the request was successful, false otherwise</returns>
            public static bool RemovePlaylistItems(
                string cookieValue,
                string playlistId,
                string videoEntityId,
                string setVideoEntityId,
                out string errorMessage)
            {
                errorMessage = string.Empty;

                if (playlistId.StartsWith("VL"))
                {
                    playlistId = playlistId.Substring(2, playlistId.Length - 2);
                }

                try
                {
                    var request = (HttpWebRequest)WebRequest.Create(
                        Global.YTMusicBaseUrl +
                        "browse/edit_playlist" +
                        Global.YTMusicParams);

                    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 <DeletePlaylistItemRequestContext>(
                        SafeFileStream.ReadAllText(
                            Path.Combine(
                                Global.WorkingDirectory,
                                @"AppData\delete_playlist_item_context.json")));

                    context.playlistId                = playlistId;
                    context.actions[0].setVideoId     = setVideoEntityId;
                    context.actions[0].removedVideoId = videoEntityId;

                    byte[] postBytes = GetPostBytes(JsonConvert.SerializeObject(context));
                    request.ContentLength = postBytes.Length;

                    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 (result.ToLower().Contains("error"))
                        {
                            errorMessage = "Error: " + result;
                            return(false);
                        }
                    }
                }
                catch (Exception e)
                {
                    errorMessage = "Error: " + e.Message;
                    return(false);
                }

                return(true);
            }