From 972af513f073a05456d6213631450d6a8657b405 Mon Sep 17 00:00:00 2001 From: max Date: Thu, 23 Oct 2025 20:08:02 +0200 Subject: [PATCH] [CHANGE] Linked decipher to video implementation --- .../Models/Innertube/StreamingFormat.cs | 3 +- Manager.YouTube/Util/Cipher/CipherDecoder.cs | 7 +++- Manager.YouTube/YouTubeClient.cs | 33 ++++++++++++++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Manager.YouTube/Models/Innertube/StreamingFormat.cs b/Manager.YouTube/Models/Innertube/StreamingFormat.cs index fab8557..8d84adc 100644 --- a/Manager.YouTube/Models/Innertube/StreamingFormat.cs +++ b/Manager.YouTube/Models/Innertube/StreamingFormat.cs @@ -3,7 +3,7 @@ namespace Manager.YouTube.Models.Innertube; public class StreamingFormat { public int Itag { get; set; } - public string Url { get; set; } = ""; + public string? Url { get; set; } public string MimeType { get; set; } = ""; public uint Bitrate { get; set; } public uint? Width { get; set; } @@ -26,5 +26,6 @@ public class StreamingFormat public int? AudioChannels { get; set; } public double? LoudnessDb { get; set; } public bool? IsDrc { get; set; } + public string? SignatureCipher { get; set; } public string QualityOrdinal { get; set; } = ""; } \ No newline at end of file diff --git a/Manager.YouTube/Util/Cipher/CipherDecoder.cs b/Manager.YouTube/Util/Cipher/CipherDecoder.cs index c917354..1dd39f3 100644 --- a/Manager.YouTube/Util/Cipher/CipherDecoder.cs +++ b/Manager.YouTube/Util/Cipher/CipherDecoder.cs @@ -31,8 +31,13 @@ public partial class CipherDecoder return decoder; } - public string Decipher(string signatureCipher) + public string Decipher(string? signatureCipher) { + if (string.IsNullOrEmpty(signatureCipher)) + { + return ""; + } + var urlBuilder = new StringBuilder(); var indexStart = signatureCipher.IndexOf("s=", StringComparison.Ordinal); diff --git a/Manager.YouTube/YouTubeClient.cs b/Manager.YouTube/YouTubeClient.cs index 83c4b7a..b8369fc 100644 --- a/Manager.YouTube/YouTubeClient.cs +++ b/Manager.YouTube/YouTubeClient.cs @@ -9,6 +9,7 @@ using Manager.YouTube.Models; using Manager.YouTube.Models.Innertube; using Manager.YouTube.Parsers; using Manager.YouTube.Parsers.Json; +using Manager.YouTube.Util.Cipher; namespace Manager.YouTube; @@ -351,8 +352,38 @@ public sealed class YouTubeClient : IDisposable return videoParseResult; } - //TODO: decipher stream urls + await DecipherSignatures(videoParseResult.Value); return videoParseResult.Value; } + + private async Task DecipherSignatures(YouTubeVideo video) + { + var streamingData = video.StreamingData; + if (streamingData == null) + { + _logger.Debug("No streaming data available, skipping decipher."); + return; + } + + var formatsWithCipher = streamingData.Formats.Concat(streamingData.AdaptiveFormats).Where(x => !string.IsNullOrWhiteSpace(x.SignatureCipher)).ToList(); + if (formatsWithCipher.Count == 0) + { + _logger.Debug("Skipping decipher, no signatures found to decipher."); + return; + } + + var decipherDecoderResult = await CipherManager.GetDecoderAsync(this); + if (!decipherDecoderResult.IsSuccess) + { + _logger.Warning(decipherDecoderResult.Error?.Description ?? "Failed to get the cipher decoder!"); + return; + } + var decoder = decipherDecoderResult.Value; + + foreach (var format in formatsWithCipher) + { + format.Url = decoder.Decipher(format.SignatureCipher); + } + } } \ No newline at end of file