diff --git a/OF DL/Program.cs b/OF DL/Program.cs index b37abd5..19dd492 100644 --- a/OF DL/Program.cs +++ b/OF DL/Program.cs @@ -1491,102 +1491,50 @@ public class Program(IServiceProvider serviceProvider) foreach (KeyValuePair purchasedPostKVP in purchasedPosts.PaidPosts) { bool isNew; + MessageEntities.Medium? mediaInfo = + purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.Id == purchasedPostKVP.Key); + PurchasedEntities.ListItem? postInfo = mediaInfo != null + ? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p => + p?.Media?.Any(m => m.Id == purchasedPostKVP.Key) == true) + : null; + string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) + .PaidPostFileNameFormat ?? ""; + string paidPostPath = configService.CurrentConfig.FolderPerPaidPost && postInfo != null && + postInfo?.Id is not null && postInfo?.PostedAt is not null + ? $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Posts/Paid"; + if (purchasedPostKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = purchasedPostKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string postId = messageUrlParsed[5]; - string? licenseURL = null; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - if (pssh == null) + string[] parsed = purchasedPostKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = + await downloadService.GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3], + parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } - DateTime lastModified = await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", - "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", - pssh); - } - - MessageEntities.Medium? mediaInfo = - purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.Id == purchasedPostKVP.Key); - PurchasedEntities.ListItem? postInfo = mediaInfo != null - ? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == purchasedPostKVP.Key) == true) - : null; - - isNew = await downloadService.DownloadPurchasedPostDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - purchasedPostKVP.Key, + isNew = await downloadService.DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, purchasedPostKVP.Key, "Posts", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidPostFileNameFormat ?? "", - postInfo, - mediaInfo, - postInfo?.FromUser, - users); - if (isNew) - { - newPaidPostCount++; - } - else - { - oldPaidPostCount++; - } + new SpectreProgressReporter(task), paidPostPath + "/Videos", filenameFormat, + postInfo, mediaInfo, postInfo?.FromUser, users); } else { - MessageEntities.Medium? mediaInfo = - purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.Id == purchasedPostKVP.Key); - PurchasedEntities.ListItem? postInfo = mediaInfo != null - ? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == purchasedPostKVP.Key) == true) - : null; + isNew = await downloadService.DownloadMedia(purchasedPostKVP.Value, path, + purchasedPostKVP.Key, "Posts", new SpectreProgressReporter(task), + paidPostPath, filenameFormat, postInfo, mediaInfo, postInfo?.FromUser, users); + } - isNew = await downloadService.DownloadPurchasedPostMedia( - purchasedPostKVP.Value, - path, - purchasedPostKVP.Key, - "Posts", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidPostFileNameFormat ?? "", - postInfo, - mediaInfo, - postInfo?.FromUser, - users); - if (isNew) - { - newPaidPostCount++; - } - else - { - oldPaidPostCount++; - } + if (isNew) + { + newPaidPostCount++; + } + else + { + oldPaidPostCount++; } } @@ -1643,101 +1591,49 @@ public class Program(IServiceProvider serviceProvider) foreach (KeyValuePair paidMessageKVP in paidMessageCollection.PaidMessages) { bool isNew; + MessageEntities.Medium? mediaInfo = + paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == paidMessageKVP.Key); + PurchasedEntities.ListItem? messageInfo = + paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => + p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); + string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) + .PaidMessageFileNameFormat ?? ""; + string paidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null && + messageInfo?.Id is not null && messageInfo?.CreatedAt is not null + ? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Messages/Paid"; + if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = paidMessageKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string messageId = messageUrlParsed[5]; - string? licenseURL = null; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - if (pssh != null) + string[] parsed = paidMessageKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = + await downloadService.GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3], + parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders( - $"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - - MessageEntities.Medium? mediaInfo = - paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => - m.Id == paidMessageKVP.Key); - PurchasedEntities.ListItem? messageInfo = - paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); - - isNew = await downloadService.DownloadPurchasedMessageDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - paidMessageKVP.Key, - "Messages", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidMessageFileNameFormat ?? "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, - users); - - if (isNew) - { - newPaidMessagesCount++; - } - else - { - oldPaidMessagesCount++; - } + continue; } + + isNew = await downloadService.DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, paidMessageKVP.Key, + "Messages", + new SpectreProgressReporter(task), paidMsgPath + "/Videos", filenameFormat, + messageInfo, mediaInfo, messageInfo?.FromUser, users); } else { - MessageEntities.Medium? mediaInfo = - paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == paidMessageKVP.Key); - PurchasedEntities.ListItem messageInfo = - paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); + isNew = await downloadService.DownloadMedia(paidMessageKVP.Value, path, + paidMessageKVP.Key, "Messages", new SpectreProgressReporter(task), + paidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users); + } - isNew = await downloadService.DownloadPurchasedMedia( - paidMessageKVP.Value, - path, - paidMessageKVP.Key, - "Messages", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidMessageFileNameFormat ?? "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, - users); - if (isNew) - { - newPaidMessagesCount++; - } - else - { - oldPaidMessagesCount++; - } + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; } } @@ -1826,6 +1722,9 @@ public class Program(IServiceProvider serviceProvider) IAPIService apiService = serviceProvider.GetRequiredService(); IDownloadService downloadService = serviceProvider.GetRequiredService(); + string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) + .PaidMessageFileNameFormat ?? ""; + Log.Debug($"Calling DownloadPaidMessage - {username}"); AnsiConsole.Markup("[red]Getting Paid Message\n[/]"); @@ -1870,102 +1769,50 @@ public class Program(IServiceProvider serviceProvider) .PreviewSingleMessages) { bool isNew; + MessageEntities.Medium? mediaInfo = + singlePaidMessageCollection.PreviewSingleMessageMedia.FirstOrDefault(m => + m.Id == paidMessageKVP.Key); + MessageEntities.SingleMessage? messageInfo = + singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => + p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); + + string previewMsgPath = configService.CurrentConfig.FolderPerMessage && messageInfo != null && + messageInfo?.Id is not null && messageInfo?.CreatedAt is not null + ? $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Messages/Free"; + if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = paidMessageKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string messageId = messageUrlParsed[5]; - string? licenseURL = null; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - if (pssh != null) + string[] parsed = paidMessageKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = + await downloadService.GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3], + parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders( - $"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - - MessageEntities.Medium? mediaInfo = - singlePaidMessageCollection.PreviewSingleMessageMedia.FirstOrDefault(m => - m.Id == paidMessageKVP.Key); - MessageEntities.SingleMessage? messageInfo = - singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); - - isNew = await downloadService.DownloadSingleMessagePreviewDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - paidMessageKVP.Key, - "Messages", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidMessageFileNameFormat ?? "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, - hasSelectedUsersKVP.Value); - - if (isNew) - { - newPreviewPaidMessagesCount++; - } - else - { - oldPreviewPaidMessagesCount++; - } + continue; } + + isNew = await downloadService.DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, paidMessageKVP.Key, + "Messages", + new SpectreProgressReporter(task), previewMsgPath + "/Videos", filenameFormat, + messageInfo, mediaInfo, messageInfo?.FromUser, hasSelectedUsersKVP.Value); } else { - MessageEntities.Medium? mediaInfo = - singlePaidMessageCollection.PreviewSingleMessageMedia.FirstOrDefault(m => - m.Id == paidMessageKVP.Key); - MessageEntities.SingleMessage? messageInfo = - singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); - - isNew = await downloadService.DownloadMessagePreviewMedia( - paidMessageKVP.Value, - path, - paidMessageKVP.Key, - "Messages", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidMessageFileNameFormat ?? "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, + isNew = await downloadService.DownloadMedia(paidMessageKVP.Value, path, + paidMessageKVP.Key, "Messages", new SpectreProgressReporter(task), + previewMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, hasSelectedUsersKVP.Value); - if (isNew) - { - newPreviewPaidMessagesCount++; - } - else - { - oldPreviewPaidMessagesCount++; - } + } + + if (isNew) + { + newPreviewPaidMessagesCount++; + } + else + { + oldPreviewPaidMessagesCount++; } } @@ -2010,93 +1857,42 @@ public class Program(IServiceProvider serviceProvider) foreach (KeyValuePair paidMessageKVP in singlePaidMessageCollection.SingleMessages) { bool isNew; + MessageEntities.Medium? mediaInfo = + singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m => + m.Id == paidMessageKVP.Key); + MessageEntities.SingleMessage? messageInfo = + singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => + p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); + string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) + .PaidMessageFileNameFormat ?? ""; + string singlePaidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && + messageInfo != null && messageInfo?.Id is not null && + messageInfo?.CreatedAt is not null + ? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Messages/Paid"; + if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = paidMessageKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string messageId = messageUrlParsed[5]; - string? licenseURL = null; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - if (pssh != null) + string[] parsed = paidMessageKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = + await downloadService.GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3], + parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders( - $"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - - MessageEntities.Medium? mediaInfo = - singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m => - m.Id == paidMessageKVP.Key); - MessageEntities.SingleMessage? messageInfo = - singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); - - isNew = await downloadService.DownloadSinglePurchasedMessageDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - paidMessageKVP.Key, - "Messages", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidMessageFileNameFormat ?? "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, - hasSelectedUsersKVP.Value); - - if (isNew) - { - newPaidMessagesCount++; - } - else - { - oldPaidMessagesCount++; - } + continue; } + + isNew = await downloadService.DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, paidMessageKVP.Key, + "Messages", + new SpectreProgressReporter(task), singlePaidMsgPath + "/Videos", filenameFormat, + messageInfo, mediaInfo, messageInfo?.FromUser, hasSelectedUsersKVP.Value); } else { - MessageEntities.Medium? mediaInfo = - singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m => - m.Id == paidMessageKVP.Key); - MessageEntities.SingleMessage? messageInfo = - singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == paidMessageKVP.Key) == true); - - isNew = await downloadService.DownloadSinglePurchasedMedia( - paidMessageKVP.Value, - path, - paidMessageKVP.Key, - "Messages", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PaidMessageFileNameFormat ?? "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, + isNew = await downloadService.DownloadMedia(paidMessageKVP.Value, path, + paidMessageKVP.Key, "Messages", new SpectreProgressReporter(task), + singlePaidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, hasSelectedUsersKVP.Value); if (isNew) { @@ -2162,83 +1958,39 @@ public class Program(IServiceProvider serviceProvider) task.StartTask(); foreach (KeyValuePair postKVP in post.SinglePosts) { + PostEntities.Medium? mediaInfo = post.SinglePostMedia.FirstOrDefault(m => m.Id == postKVP.Key); + PostEntities.SinglePost? postInfo = + post.SinglePostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); + string filenameFormat = configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) + .PostFileNameFormat ?? ""; + string postPath = configService.CurrentConfig.FolderPerPost && postInfo != null && + postInfo?.Id is not null && postInfo?.PostedAt is not null + ? $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}" + : "/Posts/Free"; + if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = postKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string postId = messageUrlParsed[5]; - string? licenseURL = null; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - if (pssh == null) + string[] parsed = postKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = + await downloadService.GetDecryptionInfo(parsed[0], parsed[1], parsed[2], parsed[3], + parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } - DateTime lastModified = await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", - "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", - pssh); - } - - PostEntities.Medium mediaInfo = post.SinglePostMedia.FirstOrDefault(m => m.Id == postKVP.Key); - PostEntities.SinglePost postInfo = - post.SinglePostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - - isNew = await downloadService.DownloadPostDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - postKVP.Key, - "Posts", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", - postInfo, - mediaInfo, - postInfo?.Author, - users); + isNew = await downloadService.DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, postKVP.Key, "Posts", + new SpectreProgressReporter(task), postPath + "/Videos", filenameFormat, + postInfo, mediaInfo, postInfo?.Author, users); } else { try { - PostEntities.Medium? mediaInfo = - post.SinglePostMedia.FirstOrDefault(m => m.Id == postKVP.Key); - PostEntities.SinglePost? postInfo = - post.SinglePostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - - isNew = await downloadService.DownloadPostMedia( - postKVP.Value, - path, - postKVP.Key, - "Posts", - new SpectreProgressReporter(task), - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username) - .PostFileNameFormat ?? "", - postInfo, - mediaInfo, - postInfo?.Author, - users); + isNew = await downloadService.DownloadMedia(postKVP.Value, path, + postKVP.Key, "Posts", new SpectreProgressReporter(task), + postPath, filenameFormat, postInfo, mediaInfo, postInfo?.Author, users); } catch { diff --git a/OF DL/Services/DownloadService.cs b/OF DL/Services/DownloadService.cs index 1e6c74d..da1b941 100644 --- a/OF DL/Services/DownloadService.cs +++ b/OF DL/Services/DownloadService.cs @@ -6,7 +6,6 @@ using FFmpeg.NET.Events; using OF_DL.Models; using OF_DL.Enumerations; using ArchivedEntities = OF_DL.Models.Entities.Archived; -using CommonEntities = OF_DL.Models.Entities.Common; using MessageEntities = OF_DL.Models.Entities.Messages; using PostEntities = OF_DL.Models.Entities.Posts; using PurchasedEntities = OF_DL.Models.Entities.Purchased; @@ -40,90 +39,12 @@ public class DownloadService( if (!string.IsNullOrEmpty(avatarUrl)) { - string avatarpath = $"{path}/Avatars"; - if (!Directory.Exists(folder + avatarpath)) - { - Directory.CreateDirectory(folder + avatarpath); - } - - List avatarMD5Hashes = CalculateFolderMD5(folder + avatarpath); - - Uri uri = new(avatarUrl); - string destinationPath = $"{folder}{avatarpath}/"; - - HttpClient client = new(); - - HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = uri }; - using HttpResponseMessage response = - await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); - response.EnsureSuccessStatusCode(); - - using MemoryStream memoryStream = new(); - await response.Content.CopyToAsync(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - - MD5 md5 = MD5.Create(); - byte[] hash = md5.ComputeHash(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - if (!avatarMD5Hashes.Contains(BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant())) - { - destinationPath = destinationPath + string.Format("{0} {1}.jpg", username, - response.Content.Headers.LastModified.HasValue - ? response.Content.Headers.LastModified.Value.LocalDateTime.ToString("dd-MM-yyyy") - : DateTime.Now.ToString("dd-MM-yyyy")); - - using (FileStream fileStream = File.Create(destinationPath)) - { - await memoryStream.CopyToAsync(fileStream); - } - - File.SetLastWriteTime(destinationPath, - response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now); - } + await DownloadProfileImage(avatarUrl, folder, $"{path}/Avatars", username); } if (!string.IsNullOrEmpty(headerUrl)) { - string headerpath = $"{path}/Headers"; - if (!Directory.Exists(folder + headerpath)) - { - Directory.CreateDirectory(folder + headerpath); - } - - List headerMD5Hashes = CalculateFolderMD5(folder + headerpath); - - Uri uri = new(headerUrl); - string destinationPath = $"{folder}{headerpath}/"; - - HttpClient client = new(); - - HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = uri }; - using HttpResponseMessage response = - await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); - response.EnsureSuccessStatusCode(); - - using MemoryStream memoryStream = new(); - await response.Content.CopyToAsync(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - - MD5 md5 = MD5.Create(); - byte[] hash = md5.ComputeHash(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - if (!headerMD5Hashes.Contains(BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant())) - { - destinationPath = destinationPath + string.Format("{0} {1}.jpg", username, - response.Content.Headers.LastModified.HasValue - ? response.Content.Headers.LastModified.Value.LocalDateTime.ToString("dd-MM-yyyy") - : DateTime.Now.ToString("dd-MM-yyyy")); - - using (FileStream fileStream = File.Create(destinationPath)) - { - await memoryStream.CopyToAsync(fileStream); - } - - File.SetLastWriteTime(destinationPath, - response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now); - } + await DownloadProfileImage(headerUrl, folder, $"{path}/Headers", username); } } catch (Exception ex) @@ -139,7 +60,48 @@ public class DownloadService( } } - #region drm common + private async Task DownloadProfileImage(string url, string folder, string subFolder, string username) + { + if (!Directory.Exists(folder + subFolder)) + { + Directory.CreateDirectory(folder + subFolder); + } + + List md5Hashes = CalculateFolderMD5(folder + subFolder); + + Uri uri = new(url); + string destinationPath = $"{folder}{subFolder}/"; + + HttpClient client = new(); + + HttpRequestMessage request = new() { Method = HttpMethod.Get, RequestUri = uri }; + using HttpResponseMessage response = + await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + + using MemoryStream memoryStream = new(); + await response.Content.CopyToAsync(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + + MD5 md5 = MD5.Create(); + byte[] hash = md5.ComputeHash(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + if (!md5Hashes.Contains(BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant())) + { + destinationPath = destinationPath + string.Format("{0} {1}.jpg", username, + response.Content.Headers.LastModified.HasValue + ? response.Content.Headers.LastModified.Value.LocalDateTime.ToString("dd-MM-yyyy") + : DateTime.Now.ToString("dd-MM-yyyy")); + + using (FileStream fileStream = File.Create(destinationPath)) + { + await memoryStream.CopyToAsync(fileStream); + } + + File.SetLastWriteTime(destinationPath, + response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now); + } + } private async Task DownloadDrmMedia(string user_agent, string policy, string signature, string kvp, string sess, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, @@ -265,8 +227,6 @@ public class DownloadService( return false; } - #endregion - private async Task OnFFMPEGDownloadComplete(string tempFilename, DateTime lastModified, string folder, string path, string customFileName, string filename, long media_id, string api_type, IProgressReporter progressReporter) { @@ -404,8 +364,6 @@ public class DownloadService( } } - #region common - /// /// /// @@ -631,7 +589,10 @@ public class DownloadService( using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); if (response.IsSuccessStatusCode) { - return response.Content.Headers.LastModified.Value.DateTime; + if (response.Content.Headers.LastModified != null) + { + return response.Content.Headers.LastModified.Value.DateTime; + } } return DateTime.Now; @@ -960,26 +921,11 @@ public class DownloadService( return totalFileSize; } - #endregion - - #region normal posts - - public async Task DownloadPostMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PostEntities.ListItem? postInfo, - PostEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users) + public async Task DownloadMedia(string url, string folder, long media_id, string api_type, + IProgressReporter progressReporter, string path, + string? filenameFormat, object? postInfo, object? postMedia, + object? author, Dictionary users) { - string path; - if (configService.CurrentConfig.FolderPerPost && postInfo != null && postInfo?.Id is not null && - postInfo?.PostedAt is not null) - { - path = $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Posts/Free"; - } - Uri uri = new(url); string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author, @@ -989,1369 +935,142 @@ public class DownloadService( filename, resolvedFilename); } - public async Task DownloadPostMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PostEntities.SinglePost? postInfo, - PostEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users) + public async Task DownloadDRMVideo(string policy, string signature, string kvp, string url, + string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, + IProgressReporter progressReporter, string path, + string? filenameFormat, object? postInfo, object? postMedia, + object? author, Dictionary users) { - string path; - if (configService.CurrentConfig.FolderPerPost && postInfo != null && postInfo?.Id is not null && - postInfo?.PostedAt is not null) + try { - path = $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}"; + Uri uri = new(url); + string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; + + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + string customFileName = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author, + folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnEmpty); + + if (!await dbService.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) + ? !File.Exists(folder + path + "/" + customFileName + ".mp4") + : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, + authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, + progressReporter, customFileName, filename, path); + } + + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) + ? folder + path + "/" + customFileName + ".mp4" + : folder + path + "/" + filename + "_source.mp4").Length; + ReportProgress(progressReporter, fileSizeInBytes); + + await dbService.UpdateMedia(folder, media_id, api_type, folder + path, + !string.IsNullOrEmpty(customFileName) ? customFileName + ".mp4" : filename + "_source.mp4", + fileSizeInBytes, true, lastModified); + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && + filename + "_source" != customFileName) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + + long size = await dbService.GetStoredFileSize(folder, media_id, api_type); + await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", + size, true, lastModified); + } + } + + if (configService.CurrentConfig.ShowScrapeSize) + { + long size = await dbService.GetStoredFileSize(folder, media_id, api_type); + progressReporter.ReportProgress(size); + } + else + { + progressReporter.ReportProgress(1); + } + } + + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, + ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, + ex.InnerException.StackTrace); + } + } + + return false; + } + + private void ReportProgress(IProgressReporter reporter, long sizeOrCount) + { + if (configService.CurrentConfig.ShowScrapeSize) + { + reporter.ReportProgress(sizeOrCount); } else { - path = "/Posts/Free"; + reporter.ReportProgress(1); } - - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author, - folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); } - public async Task DownloadStreamMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, StreamEntities.ListItem? streamInfo, - StreamEntities.Medium? streamMedia, CommonEntities.Author? author, - Dictionary users) + public async Task<(string decryptionKey, DateTime lastModified)?> GetDecryptionInfo( + string mpdURL, string policy, string signature, string kvp, + string mediaId, string contentId, string drmType, + bool clientIdBlobMissing, bool devicePrivateKeyMissing) { - string path; - if (configService.CurrentConfig.FolderPerPost && streamInfo != null && streamInfo?.Id is not null && - streamInfo?.PostedAt is not null) + string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh == null) { - path = $"/Posts/Free/{streamInfo.Id} {streamInfo.PostedAt:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Posts/Free"; + return null; } - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, streamInfo, streamMedia, - author, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); + DateTime lastModified = await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = + apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/{drmType}/{contentId}", + "?type=widevine"); + string licenseUrl = + $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/{drmType}/{contentId}?type=widevine"; - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); + string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing + ? await apiService.GetDecryptionKeyOFDL(drmHeaders, licenseUrl, pssh) + : await apiService.GetDecryptionKeyCDM(drmHeaders, licenseUrl, pssh); + + return (decryptionKey, lastModified); } - - public async Task DownloadMessageMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users) - { - string path; - if (configService.CurrentConfig.FolderPerMessage && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Messages/Free"; - } - - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, - fromUser, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); - } - - public async Task DownloadMessagePreviewMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users) - { - string path; - if (configService.CurrentConfig.FolderPerMessage && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Messages/Free"; - } - - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, - fromUser, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); - } - - - public async Task DownloadArchivedMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, ArchivedEntities.ListItem? messageInfo, - ArchivedEntities.Medium? messageMedia, CommonEntities.Author? author, - Dictionary users) - { - string path = "/Archived/Posts/Free"; - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, - author, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); - } - - - public async Task DownloadStoryMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter) - { - string path = "/Stories/Free"; - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, filename); - } - - public async Task DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, Dictionary users) - { - string path; - if (configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Messages/Paid"; - } - - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, - fromUser, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); - } - - public async Task DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users) - { - string path; - if (configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Messages/Paid"; - } - - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, - fromUser, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); - } - - public async Task DownloadPurchasedPostMedia(string url, - string folder, - long media_id, - string api_type, - IProgressReporter progressReporter, - string? filenameFormat, - PurchasedEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, - Dictionary users) - { - string path; - if (configService.CurrentConfig.FolderPerPaidPost && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.PostedAt is not null) - { - path = $"/Posts/Paid/{messageInfo.Id} {messageInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}"; - } - else - { - path = "/Posts/Paid"; - } - - Uri uri = new(url); - string filename = Path.GetFileNameWithoutExtension(uri.LocalPath); - string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, - fromUser, folder.Split("/")[^1], users, fileNameService, CustomFileNameOption.ReturnOriginal); - return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, progressReporter, - filename, resolvedFilename); - } - - #endregion - - - #region drm posts - - public async Task DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerMessage && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Messages/Free/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - - if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(messageInfo, messageMedia, - fromUser, properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - public async Task DownloadSingleMessagePreviewDRMVideo(string policy, string signature, string kvp, - string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerMessage && messageInfo != null && messageInfo?.Id is not null && - messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Messages/Free/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - - if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(messageInfo, messageMedia, - fromUser, properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - - public async Task DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null && - messageInfo?.Id is not null && messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Messages/Paid/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(messageInfo, messageMedia, - fromUser, properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - public async Task DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, - string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null && - messageInfo?.Id is not null && messageInfo?.CreatedAt is not null) - { - path = $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Messages/Paid/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(messageInfo, messageMedia, - fromUser, properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - - public async Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PostEntities.ListItem? postInfo, - PostEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerPost && postInfo != null && postInfo?.Id is not null && - postInfo?.PostedAt is not null) - { - path = $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Posts/Free/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(postInfo, postMedia, author, - properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - public async Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string filenameFormat, PostEntities.SinglePost postInfo, - PostEntities.Medium postMedia, - CommonEntities.Author author, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerPost && postInfo != null && postInfo?.Id is not null && - postInfo?.PostedAt is not null) - { - path = $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Posts/Free/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(postInfo, postMedia, author, - properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - public async Task DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, StreamEntities.ListItem? streamInfo, - StreamEntities.Medium? streamMedia, CommonEntities.Author? author, - Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerPost && streamInfo != null && streamInfo?.Id is not null && - streamInfo?.PostedAt is not null) - { - path = $"/Posts/Free/{streamInfo.Id} {streamInfo.PostedAt:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Posts/Free/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - if (!string.IsNullOrEmpty(filenameFormat) && streamInfo != null && streamMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(streamInfo, streamMedia, author, - properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - public async Task DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? postInfo, - MessageEntities.Medium? postMedia, - CommonEntities.FromUser? fromUser, Dictionary users) - { - try - { - string customFileName = ""; - string path; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - if (configService.CurrentConfig.FolderPerPaidPost && postInfo != null && postInfo?.Id is not null && - postInfo?.PostedAt is not null) - { - path = $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; - } - else - { - path = "/Posts/Paid/Videos"; - } - - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - - if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(postInfo, postMedia, fromUser, - properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - - public async Task DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, ArchivedEntities.ListItem? postInfo, - ArchivedEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users) - { - try - { - string customFileName = ""; - Uri uri = new(url); - string filename = Path.GetFileName(uri.LocalPath).Split(".")[0]; - string path = "/Archived/Posts/Free/Videos"; - if (!Directory.Exists(folder + path)) - { - Directory.CreateDirectory(folder + path); - } - - if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) - { - List properties = new(); - string pattern = @"\{(.*?)\}"; - MatchCollection matches = Regex.Matches(filenameFormat, pattern); - foreach (Match match in matches) - { - properties.Add(match.Groups[1].Value); - } - - Dictionary values = await fileNameService.GetFilename(postInfo, postMedia, author, - properties, folder.Split("/")[^1], users); - customFileName = await fileNameService.BuildFilename(filenameFormat, values); - } - - if (!await dbService.CheckDownloaded(folder, media_id, api_type)) - { - if (!string.IsNullOrEmpty(customFileName) - ? !File.Exists(folder + path + "/" + customFileName + ".mp4") - : !File.Exists(folder + path + "/" + filename + "_source.mp4")) - { - return await DownloadDrmMedia(authService.CurrentAuth.UserAgent, policy, signature, kvp, - authService.CurrentAuth.Cookie, url, decryptionKey, folder, lastModified, media_id, api_type, - progressReporter, customFileName, filename, path); - } - - long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) - ? folder + path + "/" + customFileName + ".mp4" - : folder + path + "/" + filename + "_source.mp4").Length; - if (configService.CurrentConfig.ShowScrapeSize) - { - progressReporter.ReportProgress(fileSizeInBytes); - } - else - { - progressReporter.ReportProgress(1); - } - - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, - !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", - fileSizeInBytes, true, lastModified); - } - else - { - if (!string.IsNullOrEmpty(customFileName)) - { - if (configService.CurrentConfig.RenameExistingFilesWhenCustomFormatIsSelected && - filename + "_source" != customFileName) - { - string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; - string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; - if (!File.Exists(fullPathWithTheServerFileName)) - { - return false; - } - - try - { - File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; - } - - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - await dbService.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", - size, true, lastModified); - } - } - - if (configService.CurrentConfig.ShowScrapeSize) - { - long size = await dbService.GetStoredFileSize(folder, media_id, api_type); - progressReporter.ReportProgress(size); - } - else - { - progressReporter.ReportProgress(1); - } - } - - return false; - } - catch (Exception ex) - { - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); - if (ex.InnerException != null) - { - Console.WriteLine("\nInner Exception:"); - Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, - ex.InnerException.StackTrace); - } - } - - return false; - } - - #endregion - - #region Collection Download Methods - public async Task DownloadHighlights(string username, long userId, string path, HashSet paidPostIds, IProgressReporter progressReporter) { @@ -2381,7 +1100,8 @@ public class DownloadService( foreach (KeyValuePair highlightKVP in highlights) { bool isNew = - await DownloadStoryMedia(highlightKVP.Value, path, highlightKVP.Key, "Stories", progressReporter); + await DownloadMedia(highlightKVP.Value, path, highlightKVP.Key, "Stories", progressReporter, + "/Stories/Free", null, null, null, null, new Dictionary()); if (isNew) { newHighlightsCount++; @@ -2433,7 +1153,8 @@ public class DownloadService( foreach (KeyValuePair storyKVP in stories) { - bool isNew = await DownloadStoryMedia(storyKVP.Value, path, storyKVP.Key, "Stories", progressReporter); + bool isNew = await DownloadMedia(storyKVP.Value, path, storyKVP.Key, "Stories", progressReporter, + "/Stories/Free", null, null, null, null, new Dictionary()); if (isNew) { newStoriesCount++; @@ -2484,84 +1205,33 @@ public class DownloadService( foreach (KeyValuePair archivedKVP in archived.ArchivedPosts) { bool isNew; + ArchivedEntities.Medium? mediaInfo = + archived.ArchivedPostMedia.FirstOrDefault(m => m.Id == archivedKVP.Key); + ArchivedEntities.ListItem? postInfo = + archived.ArchivedPostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); + string filenameFormat = + configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? ""; + if (archivedKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = archivedKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string postId = messageUrlParsed[5]; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - - if (pssh != null) - { - DateTime lastModified = await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", - "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", - pssh); - } - - ArchivedEntities.Medium? mediaInfo = - archived.ArchivedPostMedia.FirstOrDefault(m => m.Id == archivedKVP.Key); - ArchivedEntities.ListItem? postInfo = - archived.ArchivedPostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - - isNew = await DownloadArchivedPostDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - archivedKVP.Key, - "Posts", - progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", - postInfo, - mediaInfo, - postInfo?.Author, - users); - } - else + string[] parsed = archivedKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1], + parsed[2], parsed[3], + parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } + + isNew = await DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, archivedKVP.Key, "Posts", + progressReporter, "/Archived/Posts/Free/Videos", filenameFormat, + postInfo, mediaInfo, postInfo?.Author, users); } else { - ArchivedEntities.Medium? mediaInfo = - archived.ArchivedPostMedia.FirstOrDefault(m => m.Id == archivedKVP.Key); - ArchivedEntities.ListItem? postInfo = - archived.ArchivedPostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - - isNew = await DownloadArchivedMedia( - archivedKVP.Value, - path, - archivedKVP.Key, - "Posts", - progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", - postInfo, - mediaInfo, - postInfo?.Author, - users); + isNew = await DownloadMedia(archivedKVP.Value, path, archivedKVP.Key, "Posts", progressReporter, + "/Archived/Posts/Free", filenameFormat, postInfo, mediaInfo, postInfo?.Author, users); } if (isNew) @@ -2614,83 +1284,36 @@ public class DownloadService( foreach (KeyValuePair messageKVP in messages.Messages) { bool isNew; + MessageEntities.Medium? mediaInfo = messages.MessageMedia.FirstOrDefault(m => m.Id == messageKVP.Key); + MessageEntities.ListItem? messageInfo = messages.MessageObjects.FirstOrDefault(p => + p?.Media?.Any(m => m.Id == messageKVP.Key) == true); + string filenameFormat = + configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? ""; + string messagePath = configService.CurrentConfig.FolderPerMessage && messageInfo != null && + messageInfo?.Id is not null && messageInfo?.CreatedAt is not null + ? $"/Messages/Free/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Messages/Free"; + if (messageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] messageUrlParsed = messageKVP.Value.Split(','); - string mpdURL = messageUrlParsed[0]; - string policy = messageUrlParsed[1]; - string signature = messageUrlParsed[2]; - string kvp = messageUrlParsed[3]; - string mediaId = messageUrlParsed[4]; - string messageId = messageUrlParsed[5]; - string? pssh = await apiService.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); - - if (pssh != null) - { - DateTime lastModified = await apiService.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", - "?type=widevine"); - string decryptionKey; - if (clientIdBlobMissing || devicePrivateKeyMissing) - { - decryptionKey = await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - else - { - decryptionKey = await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", - pssh); - } - - MessageEntities.Medium? mediaInfo = - messages.MessageMedia.FirstOrDefault(m => m.Id == messageKVP.Key); - MessageEntities.ListItem? messageInfo = messages.MessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == messageKVP.Key) == true); - - isNew = await DownloadMessageDRMVideo( - policy, - signature, - kvp, - mpdURL, - decryptionKey, - path, - lastModified, - messageKVP.Key, - "Messages", - progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? - "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, - users); - } - else + string[] parsed = messageKVP.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1], + parsed[2], parsed[3], + parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } + + isNew = await DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, messageKVP.Key, "Messages", + progressReporter, messagePath + "/Videos", filenameFormat, + messageInfo, mediaInfo, messageInfo?.FromUser, users); } else { - MessageEntities.Medium? mediaInfo = messages.MessageMedia.FirstOrDefault(m => m.Id == messageKVP.Key); - MessageEntities.ListItem? messageInfo = messages.MessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == messageKVP.Key) == true); - - isNew = await DownloadMessageMedia( - messageKVP.Value, - path, - messageKVP.Key, - "Messages", - progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? - "", - messageInfo, - mediaInfo, - messageInfo?.FromUser, - users); + isNew = await DownloadMedia(messageKVP.Value, path, messageKVP.Key, "Messages", progressReporter, + messagePath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users); } if (isNew) @@ -2742,53 +1365,40 @@ public class DownloadService( int oldCount = 0; int newCount = 0; - foreach (KeyValuePair kvp in paidMessageCollection.PaidMessages) + foreach (KeyValuePair kvpEntry in paidMessageCollection.PaidMessages) { bool isNew; - if (kvp.Value.Contains("cdn3.onlyfans.com/dash/files")) + MessageEntities.Medium? mediaInfo = + paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == kvpEntry.Key); + PurchasedEntities.ListItem? messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => + p?.Media?.Any(m => m.Id == kvpEntry.Key) == true); + string filenameFormat = + configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? ""; + string paidMsgPath = configService.CurrentConfig.FolderPerPaidMessage && messageInfo != null && + messageInfo?.Id is not null && messageInfo?.CreatedAt is not null + ? $"/Messages/Paid/{messageInfo.Id} {messageInfo.CreatedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Messages/Paid"; + + if (kvpEntry.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] parsed = kvp.Value.Split(','); - string? pssh = await apiService.GetDRMMPDPSSH(parsed[0], parsed[1], parsed[2], parsed[3]); - if (pssh != null) - { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(parsed[0], parsed[1], parsed[2], parsed[3]); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{parsed[4]}/drm/message/{parsed[5]}", - "?type=widevine"); - string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing - ? await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/message/{parsed[5]}?type=widevine", - pssh) - : await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/message/{parsed[5]}?type=widevine", - pssh); - - MessageEntities.Medium? mediaInfo = - paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == kvp.Key); - PurchasedEntities.ListItem? messageInfo = - paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == kvp.Key) == true); - - isNew = await DownloadPurchasedMessageDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], - decryptionKey, path, lastModified, kvp.Key, "Messages", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? - "", messageInfo, mediaInfo, messageInfo?.FromUser, users); - } - else + string[] parsed = kvpEntry.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1], + parsed[2], parsed[3], + parsed[4], parsed[5], "message", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } + + isNew = await DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, kvpEntry.Key, "Messages", + progressReporter, paidMsgPath + "/Videos", filenameFormat, + messageInfo, mediaInfo, messageInfo?.FromUser, users); } else { - MessageEntities.Medium? mediaInfo = - paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.Id == kvp.Key); - PurchasedEntities.ListItem? messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == kvp.Key) == true); - isNew = await DownloadPurchasedMedia(kvp.Value, path, kvp.Key, "Messages", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).MessageFileNameFormat ?? - "", messageInfo, mediaInfo, messageInfo?.FromUser, users); + isNew = await DownloadMedia(kvpEntry.Value, path, kvpEntry.Key, "Messages", progressReporter, + paidMsgPath, filenameFormat, messageInfo, mediaInfo, messageInfo?.FromUser, users); } if (isNew) @@ -2836,50 +1446,39 @@ public class DownloadService( int oldCount = 0; int newCount = 0; - foreach (KeyValuePair kvp in streams.Streams) + foreach (KeyValuePair kvpEntry in streams.Streams) { bool isNew; - if (kvp.Value.Contains("cdn3.onlyfans.com/dash/files")) + StreamEntities.Medium? mediaInfo = streams.StreamMedia.FirstOrDefault(m => m.Id == kvpEntry.Key); + StreamEntities.ListItem? streamInfo = + streams.StreamObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); + string filenameFormat = + configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? ""; + string streamPath = configService.CurrentConfig.FolderPerPost && streamInfo != null && + streamInfo?.Id is not null && streamInfo?.PostedAt is not null + ? $"/Posts/Free/{streamInfo.Id} {streamInfo.PostedAt:yyyy-MM-dd HH-mm-ss}" + : "/Posts/Free"; + + if (kvpEntry.Value.Contains("cdn3.onlyfans.com/dash/files")) { - string[] parsed = kvp.Value.Split(','); - string? pssh = await apiService.GetDRMMPDPSSH(parsed[0], parsed[1], parsed[2], parsed[3]); - if (pssh != null) - { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(parsed[0], parsed[1], parsed[2], parsed[3]); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}", - "?type=widevine"); - string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing - ? await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}?type=widevine", - pssh) - : await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}?type=widevine", - pssh); - - StreamEntities.Medium? mediaInfo = streams.StreamMedia.FirstOrDefault(m => m.Id == kvp.Key); - StreamEntities.ListItem? streamInfo = - streams.StreamObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - - isNew = await DownloadStreamsDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], decryptionKey, - path, lastModified, kvp.Key, "Streams", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", streamInfo, mediaInfo, streamInfo?.Author, users); - } - else + string[] parsed = kvpEntry.Value.Split(','); + (string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1], + parsed[2], parsed[3], + parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } + + isNew = await DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, kvpEntry.Key, "Streams", + progressReporter, streamPath + "/Videos", filenameFormat, + streamInfo, mediaInfo, streamInfo?.Author, users); } else { - StreamEntities.Medium? mediaInfo = streams.StreamMedia.FirstOrDefault(m => m.Id == kvp.Key); - StreamEntities.ListItem? streamInfo = - streams.StreamObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - isNew = await DownloadStreamMedia(kvp.Value, path, kvp.Key, "Streams", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", streamInfo, mediaInfo, streamInfo?.Author, users); + isNew = await DownloadMedia(kvpEntry.Value, path, kvpEntry.Key, "Streams", progressReporter, + streamPath, filenameFormat, streamInfo, mediaInfo, streamInfo?.Author, users); } if (isNew) @@ -2903,8 +1502,6 @@ public class DownloadService( }; } -// Add these methods to DownloadService.cs before the #endregion line - public async Task DownloadFreePosts(string username, long userId, string path, Dictionary users, bool clientIdBlobMissing, bool devicePrivateKeyMissing, PostEntities.PostCollection posts, @@ -2932,47 +1529,36 @@ public class DownloadService( foreach (KeyValuePair postKVP in posts.Posts) { bool isNew; + PostEntities.Medium? mediaInfo = posts.PostMedia.FirstOrDefault(m => m?.Id == postKVP.Key); + PostEntities.ListItem? postInfo = + posts.PostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); + string filenameFormat = + configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? ""; + string postPath = configService.CurrentConfig.FolderPerPost && postInfo != null && + postInfo?.Id is not null && postInfo?.PostedAt is not null + ? $"/Posts/Free/{postInfo.Id} {postInfo.PostedAt:yyyy-MM-dd HH-mm-ss}" + : "/Posts/Free"; + if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { string[] parsed = postKVP.Value.Split(','); - string? pssh = await apiService.GetDRMMPDPSSH(parsed[0], parsed[1], parsed[2], parsed[3]); - if (pssh != null) - { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(parsed[0], parsed[1], parsed[2], parsed[3]); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}", - "?type=widevine"); - string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing - ? await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}?type=widevine", - pssh) - : await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}?type=widevine", - pssh); - - PostEntities.Medium mediaInfo = posts.PostMedia.FirstOrDefault(m => m.Id == postKVP.Key); - PostEntities.ListItem postInfo = - posts.PostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - - isNew = await DownloadPostDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], decryptionKey, path, - lastModified, postKVP.Key, "Posts", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", postInfo, mediaInfo, postInfo?.Author, users); - } - else + (string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1], + parsed[2], parsed[3], + parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } + + isNew = await DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, postKVP.Key, "Posts", + progressReporter, postPath + "/Videos", filenameFormat, + postInfo, mediaInfo, postInfo?.Author, users); } else { - PostEntities.Medium? mediaInfo = posts.PostMedia.FirstOrDefault(m => m?.Id == postKVP.Key); - PostEntities.ListItem? postInfo = - posts.PostObjects.FirstOrDefault(p => p?.Media?.Contains(mediaInfo) == true); - isNew = await DownloadPostMedia(postKVP.Value, path, postKVP.Key, "Posts", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", postInfo, mediaInfo, postInfo?.Author, users); + isNew = await DownloadMedia(postKVP.Value, path, postKVP.Key, "Posts", progressReporter, + postPath, filenameFormat, postInfo, mediaInfo, postInfo?.Author, users); } if (isNew) @@ -3023,50 +1609,37 @@ public class DownloadService( foreach (KeyValuePair postKVP in purchasedPosts.PaidPosts) { bool isNew; + MessageEntities.Medium? mediaInfo = + purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.Id == postKVP.Key); + PurchasedEntities.ListItem? postInfo = + purchasedPosts.PaidPostObjects.FirstOrDefault(p => p?.Media?.Any(m => m.Id == postKVP.Key) == true); + string filenameFormat = + configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? ""; + string paidPostPath = configService.CurrentConfig.FolderPerPaidPost && postInfo != null && + postInfo?.Id is not null && postInfo?.PostedAt is not null + ? $"/Posts/Paid/{postInfo.Id} {postInfo.PostedAt.Value:yyyy-MM-dd HH-mm-ss}" + : "/Posts/Paid"; + if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) { string[] parsed = postKVP.Value.Split(','); - string? pssh = await apiService.GetDRMMPDPSSH(parsed[0], parsed[1], parsed[2], parsed[3]); - if (pssh != null) - { - DateTime lastModified = - await apiService.GetDRMMPDLastModified(parsed[0], parsed[1], parsed[2], parsed[3]); - Dictionary drmHeaders = - apiService.GetDynamicHeaders($"/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}", - "?type=widevine"); - string decryptionKey = clientIdBlobMissing || devicePrivateKeyMissing - ? await apiService.GetDecryptionKeyOFDL(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}?type=widevine", - pssh) - : await apiService.GetDecryptionKeyCDM(drmHeaders, - $"https://onlyfans.com/api2/v2/users/media/{parsed[4]}/drm/post/{parsed[5]}?type=widevine", - pssh); - - MessageEntities.Medium? mediaInfo = - purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.Id == postKVP.Key); - PurchasedEntities.ListItem? postInfo = - purchasedPosts.PaidPostObjects.FirstOrDefault(p => - p?.Media?.Any(m => m.Id == postKVP.Key) == true); - - isNew = await DownloadPurchasedPostDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], - decryptionKey, path, lastModified, postKVP.Key, "Posts", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", postInfo, mediaInfo, postInfo?.FromUser, users); - } - else + (string decryptionKey, DateTime lastModified)? drmInfo = await GetDecryptionInfo(parsed[0], parsed[1], + parsed[2], parsed[3], + parsed[4], parsed[5], "post", clientIdBlobMissing, devicePrivateKeyMissing); + if (drmInfo == null) { continue; } + + isNew = await DownloadDRMVideo(parsed[1], parsed[2], parsed[3], parsed[0], + drmInfo.Value.decryptionKey, path, drmInfo.Value.lastModified, postKVP.Key, "Posts", + progressReporter, paidPostPath + "/Videos", filenameFormat, + postInfo, mediaInfo, postInfo?.FromUser, users); } else { - MessageEntities.Medium? mediaInfo = - purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.Id == postKVP.Key); - PurchasedEntities.ListItem? postInfo = - purchasedPosts.PaidPostObjects.FirstOrDefault(p => p?.Media?.Any(m => m.Id == postKVP.Key) == true); - isNew = await DownloadPurchasedPostMedia(postKVP.Value, path, postKVP.Key, "Posts", progressReporter, - configService.CurrentConfig.GetCreatorFileNameFormatConfig(username).PostFileNameFormat ?? - "", postInfo, mediaInfo, postInfo?.FromUser, users); + isNew = await DownloadMedia(postKVP.Value, path, postKVP.Key, "Posts", progressReporter, + paidPostPath, filenameFormat, postInfo, mediaInfo, postInfo?.FromUser, users); } if (isNew) @@ -3089,6 +1662,4 @@ public class DownloadService( Success = true }; } - - #endregion } diff --git a/OF DL/Services/IDownloadService.cs b/OF DL/Services/IDownloadService.cs index 14f5f58..c46996a 100644 --- a/OF DL/Services/IDownloadService.cs +++ b/OF DL/Services/IDownloadService.cs @@ -1,6 +1,5 @@ using OF_DL.Models; using ArchivedEntities = OF_DL.Models.Entities.Archived; -using CommonEntities = OF_DL.Models.Entities.Common; using MessageEntities = OF_DL.Models.Entities.Messages; using PostEntities = OF_DL.Models.Entities.Posts; using PurchasedEntities = OF_DL.Models.Entities.Purchased; @@ -15,105 +14,24 @@ public interface IDownloadService Task ProcessMediaDownload(string folder, long media_id, string api_type, string url, string path, string serverFileName, string resolvedFileName, string extension, IProgressReporter progressReporter); - Task DownloadArchivedMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, ArchivedEntities.ListItem? messageInfo, - ArchivedEntities.Medium? messageMedia, CommonEntities.Author? author, - Dictionary users); + Task DownloadMedia(string url, string folder, long media_id, string api_type, + IProgressReporter progressReporter, string path, + string? filenameFormat, object? postInfo, object? postMedia, + object? author, Dictionary users); - Task DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, + Task DownloadDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, ArchivedEntities.ListItem? postInfo, - ArchivedEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users); + IProgressReporter progressReporter, string path, + string? filenameFormat, object? postInfo, object? postMedia, + object? author, Dictionary users); - Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, - string folder, DateTime lastModified, long media_id, string api_type, IProgressReporter progressReporter, - string filenameFormat, PostEntities.SinglePost postInfo, PostEntities.Medium postMedia, - CommonEntities.Author author, - Dictionary users); - - Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, - string folder, DateTime lastModified, long media_id, string api_type, IProgressReporter progressReporter, - string? filenameFormat, PostEntities.ListItem? postInfo, PostEntities.Medium? postMedia, - CommonEntities.Author? author, - Dictionary users); + Task<(string decryptionKey, DateTime lastModified)?> GetDecryptionInfo( + string mpdURL, string policy, string signature, string kvp, + string mediaId, string contentId, string drmType, + bool clientIdBlobMissing, bool devicePrivateKeyMissing); Task DownloadAvatarHeader(string? avatarUrl, string? headerUrl, string folder, string username); - Task DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, - string folder, DateTime lastModified, long media_id, string api_type, IProgressReporter progressReporter, - string? filenameFormat, MessageEntities.ListItem? messageInfo, MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, - Dictionary users); - - Task DownloadMessageMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadPostMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PostEntities.ListItem? postInfo, - PostEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users); - - Task DownloadPostMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PostEntities.SinglePost? postInfo, - PostEntities.Medium? postMedia, - CommonEntities.Author? author, Dictionary users); - - Task DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? postInfo, - MessageEntities.Medium? postMedia, - CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadPurchasedPostMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, PurchasedEntities.ListItem? messageInfo, - MessageEntities.Medium? messageMedia, - CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadStoryMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter); - - Task DownloadStreamMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, StreamEntities.ListItem? streamInfo, - StreamEntities.Medium? streamMedia, CommonEntities.Author? author, - Dictionary users); - - Task DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, - string folder, DateTime lastModified, long media_id, string api_type, IProgressReporter progressReporter, - string? filenameFormat, StreamEntities.ListItem? streamInfo, StreamEntities.Medium? streamMedia, - CommonEntities.Author? author, - Dictionary users); - - Task DownloadSingleMessagePreviewDRMVideo(string policy, string signature, string kvp, string url, - string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users); - - Task DownloadMessagePreviewMedia(string url, string folder, long media_id, string api_type, - IProgressReporter progressReporter, string? filenameFormat, MessageEntities.SingleMessage? messageInfo, - MessageEntities.Medium? messageMedia, CommonEntities.FromUser? fromUser, Dictionary users); - Task DownloadHighlights(string username, long userId, string path, HashSet paidPostIds, IProgressReporter progressReporter);