private static async Task GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp) { try { HttpClient client = new HttpClient(); var request = new HttpRequestMessage { RequestUri = new Uri(mpdUrl), Method = HttpMethod.Get, }; request.Headers.Add("Accept", "application/dash+xml,video/vnd.mpeg.dash.mpd"); request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"); request.Headers.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}"); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); string mpdContent = await response.Content.ReadAsStringAsync(); XDocument mpdDoc = XDocument.Parse(mpdContent); XNamespace ns = "urn:mpeg:dash:schema:mpd:2011"; var psshElement = mpdDoc.Descendants(ns + "PSSH").FirstOrDefault(); return psshElement?.Value; } catch (Exception ex) { Log.Error("Error getting PSSH: {0}", ex.Message); return null; } } private static async Task GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp) { try { HttpClient client = new HttpClient(); var request = new HttpRequestMessage { RequestUri = new Uri(mpdUrl), Method = HttpMethod.Head, }; request.Headers.Add("Accept", "application/dash+xml,video/vnd.mpeg.dash.mpd"); request.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"); request.Headers.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}"); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); return response.Content.Headers.LastModified?.DateTime ?? DateTime.Now; } catch (Exception ex) { Log.Error("Error getting MPD last modified date: {0}", ex.Message); return DateTime.Now; } } private static Dictionary GetDynamicHeaders(string url, string queryParams) { var headers = new Dictionary(); try { headers = auth.GetDynamicHeaders(url, queryParams); } catch (Exception ex) { Log.Error("Error getting dynamic headers: {0}", ex.Message); } return headers; } private static async Task GetDecryptionKeyOFDL(Dictionary drmHeaders, string licenseUrl, string pssh) { try { var client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Post, "https://ofdl.tools/wv") { Content = new FormUrlEncodedContent(new Dictionary { { "license_url", licenseUrl }, { "headers", JsonConvert.SerializeObject(drmHeaders) }, { "pssh", pssh }, { "build_identifier", "windows_software_widevinecdm_win_x86_64" }, { { "proxy", "" } }) }; var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); var responseContent = await response.Content.ReadAsStringAsync(); var jsonResponse = JObject.Parse(responseContent); return jsonResponse["keys"][0]["key"].ToString(); } catch (Exception ex) { Log.Error("Error getting decryption key from OFDL: {0}", ex.Message); throw; } } private static async Task GetDecryptionKeyCDM(Dictionary drmHeaders, string licenseUrl, string pssh) { try { var client = new WidevineClient.Widevine.CDMClient(); return await client.GetContentKey(licenseUrl, drmHeaders, pssh); } catch (Exception ex) { Log.Error("Error getting decryption key from CDM: {0}", ex.Message); throw; } } private static async Task DownloadPurchasedMessageDRMVideo( string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, User? fromUser, Dictionary users) { try { string filename = string.Empty; string customFileName = string.Empty; string path = string.Empty; if (messageInfo != null && messageMedia != null && fromUser != null) { filename = await DownloadHelper.GenerateFilename(filenameFormat, "Messages", messageInfo, messageMedia, fromUser, users, api_type); customFileName = filename.Split('.')[0]; path = Path.Combine(folder, filename); } else { filename = $"{media_id}.mp4"; path = Path.Combine(folder, filename); } if (File.Exists(path) && new FileInfo(path).Length > 0) { return false; } var downloader = new DownloadHelper.DRMVideoDownloader(); await downloader.DownloadDRMVideo( url: url, decryptionKey: decryptionKey, folder: folder, lastModified: lastModified, policy: policy, signature: signature, kvp: kvp, customFileName: customFileName, task: task); return true; } catch (Exception ex) { Log.Error("Error downloading DRM video: {0}", ex.Message); return false; } } private static async Task DownloadPurchasedMedia( string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, User? fromUser, Dictionary users) { try { string filename = string.Empty; string path = string.Empty; if (messageInfo != null && messageMedia != null && fromUser != null) { filename = await DownloadHelper.GenerateFilename(filenameFormat, "Messages", messageInfo, messageMedia, fromUser, users, api_type); path = Path.Combine(folder, filename); } else { filename = $"{media_id}.mp4"; path = Path.Combine(folder, filename); } if (File.Exists(path) && new FileInfo(path).Length > 0) { return false; } var downloader = new DownloadHelper.MediaDownloader(); await downloader.DownloadMedia( url: url, folder: folder, filename: filename, task: task); return true; } catch (Exception ex) { Log.Error("Error downloading media: {0}", ex.Message); return false; } }