This commit is contained in:
sim0n00ps 2025-05-06 00:34:15 +01:00
parent 4abbf1162d
commit dd2b7cd82c
7 changed files with 158 additions and 24 deletions

View File

@ -100,6 +100,9 @@ namespace OF_DL.Entities
[ToggleableConfig]
public bool DisableBrowserAuth { get; set; } = false;
[JsonConverter(typeof(StringEnumConverter))]
public VideoResolution DownloadVideoResolution { get; set; } = VideoResolution.source;
}
public class CreatorConfig : IFileNameFormatConfig

View File

@ -17,6 +17,8 @@ namespace OF_DL.Entities
bool DownloadVideos { get; set; }
bool DownloadAudios { get; set; }
VideoResolution DownloadVideoResolution { get; set; }
int? Timeout { get; set; }
bool FolderPerPaidPost { get; set; }
bool FolderPerPost { get; set; }

View File

@ -150,10 +150,10 @@ namespace OF_DL.Entities.Post
public class VideoSources
{
[JsonProperty("720")]
public object _720 { get; set; }
public string _720 { get; set; }
[JsonProperty("240")]
public object _240 { get; set; }
public string _240 { get; set; }
}
public class Dash
{

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OF_DL.Enumerations
{
public enum VideoResolution
{
_240,
_720,
source
}
}

View File

@ -9,6 +9,7 @@ using OF_DL.Entities.Post;
using OF_DL.Entities.Purchased;
using OF_DL.Entities.Stories;
using OF_DL.Entities.Streams;
using OF_DL.Enumerations;
using OF_DL.Enumurations;
using Serilog;
using Spectre.Console;
@ -26,6 +27,7 @@ public class APIHelper : IAPIHelper
{
private static readonly JsonSerializerSettings m_JsonSerializerSettings;
private readonly IDBHelper m_DBHelper;
private readonly IDownloadConfig downloadConfig;
private readonly Auth auth;
private static DateTime? cachedDynamicRulesExpiration;
private static DynamicRules? cachedDynamicRules;
@ -42,6 +44,7 @@ public class APIHelper : IAPIHelper
{
this.auth = auth;
m_DBHelper = new DBHelper(downloadConfig);
this.downloadConfig = downloadConfig;
}
@ -1130,6 +1133,9 @@ public class APIHelper : IAPIHelper
}
if (medium.canView && medium.files?.drm == null)
{
switch (downloadConfig.DownloadVideoResolution)
{
case VideoResolution.source:
if (medium.files!.full != null && !string.IsNullOrEmpty(medium.files!.full.url))
{
if (!medium.files!.full.url.Contains("upload"))
@ -1142,18 +1148,37 @@ public class APIHelper : IAPIHelper
}
}
}
else if (medium.files.preview != null && medium.files!.full == null)
break;
case VideoResolution._240:
if(medium.videoSources != null)
{
if (!medium.files.preview.url.Contains("upload"))
if (!string.IsNullOrEmpty(medium.videoSources._240))
{
if (!singlePostCollection.SinglePosts.ContainsKey(medium.id))
{
await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.files.preview.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null);
singlePostCollection.SinglePosts.Add(medium.id, medium.files.preview.url);
await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.videoSources._240, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null);
singlePostCollection.SinglePosts.Add(medium.id, medium.videoSources._240);
singlePostCollection.SinglePostMedia.Add(medium);
}
}
}
break;
case VideoResolution._720:
if (medium.videoSources != null)
{
if (!string.IsNullOrEmpty(medium.videoSources._720))
{
if (!singlePostCollection.SinglePosts.ContainsKey(medium.id))
{
await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.videoSources._720, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null);
singlePostCollection.SinglePosts.Add(medium.id, medium.videoSources._720);
singlePostCollection.SinglePostMedia.Add(medium);
}
}
}
break;
}
}
else if (medium.canView && medium.files != null && medium.files.drm != null)
{
@ -1167,6 +1192,18 @@ public class APIHelper : IAPIHelper
}
}
}
else if (medium.files.preview != null && medium.files!.full == null)
{
if (!medium.files.preview.url.Contains("upload"))
{
if (!singlePostCollection.SinglePosts.ContainsKey(medium.id))
{
await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.files.preview.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null);
singlePostCollection.SinglePosts.Add(medium.id, medium.files.preview.url);
singlePostCollection.SinglePostMedia.Add(medium);
}
}
}
}
}
}

View File

@ -12,6 +12,7 @@ using OF_DL.Enumerations;
using OF_DL.Utils;
using Org.BouncyCastle.Asn1.Tsp;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Tsp;
using Serilog;
using Spectre.Console;
using System;
@ -25,6 +26,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using static OF_DL.Entities.Lists.UserList;
using static OF_DL.Entities.Messages.Messages;
@ -602,9 +604,30 @@ public class DownloadHelper : IDownloadHelper
decKey = decryptionKey.Substring(pos1 + 1);
}
string tempFilename = $"{folder}{path}/{filename}_source.mp4";
int? streamIndex = await GetVideoStreamIndexFromMpd(url, policy, signature, kvp, downloadConfig.DownloadVideoResolution);
string parameters = $"-cenc_decryption_key {decKey} -headers \"Cookie:CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {sess} Origin: https://onlyfans.com Referer: https://onlyfans.com User-Agent: {user_agent}\" -y -i \"{url}\" -codec copy \"{tempFilename}\"";
if (streamIndex == null)
throw new Exception($"Could not find video stream for resolution {downloadConfig.DownloadVideoResolution}");
string tempFilename;
switch (downloadConfig.DownloadVideoResolution)
{
case VideoResolution.source:
tempFilename = $"{folder}{path}/{filename}_source.mp4";
break;
case VideoResolution._240:
tempFilename = $"{folder}{path}/{filename}_240.mp4";
break;
case VideoResolution._720:
tempFilename = $"{folder}{path}/{filename}_720.mp4";
break;
default:
tempFilename = $"{folder}{path}/{filename}_source.mp4";
break;
}
string parameters = $"-cenc_decryption_key {decKey} -headers \"Cookie:CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {sess} Origin: https://onlyfans.com Referer: https://onlyfans.com User-Agent: {user_agent}\" -y -i \"{url}\" -map 0:v:{streamIndex} -map 0:a? -codec copy \"{tempFilename}\"";
Log.Debug($"Calling FFMPEG with Parameters: {parameters}");
@ -1787,4 +1810,45 @@ public class DownloadHelper : IDownloadHelper
return false;
}
#endregion
private async Task <int?> GetVideoStreamIndexFromMpd(string mpdUrl, string policy, string signature, string kvp, VideoResolution resolution)
{
HttpClient client = new();
HttpRequestMessage request = new(HttpMethod.Get, mpdUrl);
request.Headers.Add("user-agent", auth.USER_AGENT);
request.Headers.Add("Accept", "*/*");
request.Headers.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {auth.COOKIE};");
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
XDocument doc = XDocument.Parse(body);
XNamespace ns = "urn:mpeg:dash:schema:mpd:2011";
XNamespace cenc = "urn:mpeg:cenc:2013";
var videoAdaptationSet = doc
.Descendants(ns + "AdaptationSet")
.FirstOrDefault(e => (string)e.Attribute("mimeType") == "video/mp4");
if (videoAdaptationSet == null)
return null;
string targetHeight = resolution switch
{
VideoResolution._240 => "240",
VideoResolution._720 => "720",
VideoResolution.source => "1280",
_ => throw new ArgumentOutOfRangeException(nameof(resolution))
};
var representations = videoAdaptationSet.Elements(ns + "Representation").ToList();
for (int i = 0; i < representations.Count; i++)
{
if ((string)representations[i].Attribute("height") == targetHeight)
return i; // this is the index FFmpeg will use for `-map 0:v:{i}`
}
}
return null;
}
}

View File

@ -161,6 +161,7 @@ public class Program
hoconConfig.AppendLine($" DownloadDateSelection = \"{jsonConfig.DownloadDateSelection.ToString().ToLower()}\"");
hoconConfig.AppendLine($" CustomDate = \"{jsonConfig.CustomDate?.ToString("yyyy-MM-dd")}\"");
hoconConfig.AppendLine($" ShowScrapeSize = {jsonConfig.ShowScrapeSize.ToString().ToLower()}");
hoconConfig.AppendLine($" DownloadVideoResolution = \"{(jsonConfig.DownloadVideoResolution == VideoResolution.source ? "source" : jsonConfig.DownloadVideoResolution.ToString().TrimStart('_'))}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# File Settings");
@ -280,6 +281,7 @@ public class Program
DownloadDateSelection = Enum.Parse<DownloadDateSelection>(hoconConfig.GetString("Download.DownloadDateSelection"), true),
CustomDate = !string.IsNullOrWhiteSpace(hoconConfig.GetString("Download.CustomDate")) ? DateTime.Parse(hoconConfig.GetString("Download.CustomDate")) : null,
ShowScrapeSize = hoconConfig.GetBoolean("Download.ShowScrapeSize"),
DownloadVideoResolution = ParseVideoResolution(hoconConfig.GetString("Download.DownloadVideoResolution")),
// File Settings
PaidPostFileNameFormat = hoconConfig.GetString("File.PaidPostFileNameFormat"),
@ -399,6 +401,7 @@ public class Program
hoconConfig.AppendLine($" DownloadDateSelection = \"{jsonConfig.DownloadDateSelection.ToString().ToLower()}\"");
hoconConfig.AppendLine($" CustomDate = \"{jsonConfig.CustomDate?.ToString("yyyy-MM-dd")}\"");
hoconConfig.AppendLine($" ShowScrapeSize = {jsonConfig.ShowScrapeSize.ToString().ToLower()}");
hoconConfig.AppendLine($" DownloadVideoResolution = \"{(jsonConfig.DownloadVideoResolution == VideoResolution.source ? "source" : jsonConfig.DownloadVideoResolution.ToString().TrimStart('_'))}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# File Settings");
@ -2862,6 +2865,7 @@ public class Program
hoconConfig.AppendLine($" DownloadDateSelection = \"{newConfig.DownloadDateSelection.ToString().ToLower()}\"");
hoconConfig.AppendLine($" CustomDate = \"{newConfig.CustomDate?.ToString("yyyy-MM-dd")}\"");
hoconConfig.AppendLine($" ShowScrapeSize = {newConfig.ShowScrapeSize.ToString().ToLower()}");
hoconConfig.AppendLine($" DownloadVideoResolution = \"{(newConfig.DownloadVideoResolution == VideoResolution.source ? "source" : newConfig.DownloadVideoResolution.ToString().TrimStart('_'))}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# File Settings");
@ -3020,6 +3024,7 @@ public class Program
hoconConfig.AppendLine($" DownloadDateSelection = \"{newConfig.DownloadDateSelection.ToString().ToLower()}\"");
hoconConfig.AppendLine($" CustomDate = \"{newConfig.CustomDate?.ToString("yyyy-MM-dd")}\"");
hoconConfig.AppendLine($" ShowScrapeSize = {newConfig.ShowScrapeSize.ToString().ToLower()}");
hoconConfig.AppendLine($" DownloadVideoResolution = \"{(newConfig.DownloadVideoResolution == VideoResolution.source ? "source" : newConfig.DownloadVideoResolution.ToString().TrimStart('_'))}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# File Settings");
@ -3238,4 +3243,12 @@ public class Program
Environment.Exit(2);
}
}
public static VideoResolution ParseVideoResolution(string value)
{
if (value.Equals("source", StringComparison.OrdinalIgnoreCase))
return VideoResolution.source;
return Enum.Parse<VideoResolution>("_" + value, ignoreCase: true);
}
}