revert 14d2411e88ddbcb0a86753ecfed994c4b792e787

revert merge upstream
This commit is contained in:
nyc_tk 2025-12-14 22:20:20 +00:00
parent 14d2411e88
commit be7339dca0
26 changed files with 241 additions and 389 deletions

View File

@ -17,7 +17,7 @@ namespace OF_DL.Entities.Archived
public Counters counters { get; set; } public Counters counters { get; set; }
public class Author public class Author
{ {
public long id { get; set; } public int id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
@ -64,7 +64,7 @@ namespace OF_DL.Entities.Archived
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -73,7 +73,7 @@ namespace OF_DL.Entities.Archived
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Thumb public class Thumb
@ -81,7 +81,7 @@ namespace OF_DL.Entities.Archived
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Hls public class Hls
@ -105,7 +105,7 @@ namespace OF_DL.Entities.Archived
public class LinkedPost public class LinkedPost
{ {
public string responseType { get; set; } public string responseType { get; set; }
public long? id { get; set; } public int? id { get; set; }
public DateTime? postedAt { get; set; } public DateTime? postedAt { get; set; }
public string postedAtPrecise { get; set; } public string postedAtPrecise { get; set; }
public object expiredAt { get; set; } public object expiredAt { get; set; }

View File

@ -9,10 +9,10 @@ namespace OF_DL.Entities.Highlights
{ {
public class HighlightMedia public class HighlightMedia
{ {
public long id { get; set; } public int id { get; set; }
public long userId { get; set; } public int userId { get; set; }
public string title { get; set; } public string title { get; set; }
public long coverStoryId { get; set; } public int coverStoryId { get; set; }
public string cover { get; set; } public string cover { get; set; }
public int storiesCount { get; set; } public int storiesCount { get; set; }
public DateTime? createdAt { get; set; } public DateTime? createdAt { get; set; }
@ -30,7 +30,7 @@ namespace OF_DL.Entities.Highlights
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -50,7 +50,7 @@ namespace OF_DL.Entities.Highlights
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public Sources sources { get; set; } public Sources sources { get; set; }
} }
@ -60,7 +60,7 @@ namespace OF_DL.Entities.Highlights
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public int duration { get; set; } public int duration { get; set; }
public long size { get; set; } public int size { get; set; }
public Sources sources { get; set; } public Sources sources { get; set; }
} }
@ -80,14 +80,14 @@ namespace OF_DL.Entities.Highlights
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public Sources sources { get; set; } public Sources sources { get; set; }
} }
public class Story public class Story
{ {
public long id { get; set; } public int id { get; set; }
public long userId { get; set; } public int userId { get; set; }
public bool isWatched { get; set; } public bool isWatched { get; set; }
public bool isReady { get; set; } public bool isReady { get; set; }
public List<Medium> media { get; set; } public List<Medium> media { get; set; }
@ -102,7 +102,7 @@ namespace OF_DL.Entities.Highlights
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
} }
} }

View File

@ -12,10 +12,10 @@ namespace OF_DL.Entities.Highlights
public bool hasMore { get; set; } public bool hasMore { get; set; }
public class List public class List
{ {
public long id { get; set; } public int id { get; set; }
public long userId { get; set; } public int userId { get; set; }
public string title { get; set; } public string title { get; set; }
public long coverStoryId { get; set; } public int coverStoryId { get; set; }
public string cover { get; set; } public string cover { get; set; }
public int storiesCount { get; set; } public int storiesCount { get; set; }
public DateTime? createdAt { get; set; } public DateTime? createdAt { get; set; }

View File

@ -34,7 +34,7 @@ namespace OF_DL.Entities.Lists
public class User public class User
{ {
public long? id { get; set; } public int? id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
} }

View File

@ -14,7 +14,7 @@ namespace OF_DL.Entities.Lists
public string header { get; set; } public string header { get; set; }
public HeaderSize headerSize { get; set; } public HeaderSize headerSize { get; set; }
public HeaderThumbs headerThumbs { get; set; } public HeaderThumbs headerThumbs { get; set; }
public long? id { get; set; } public int? id { get; set; }
public string name { get; set; } public string name { get; set; }
public string username { get; set; } public string username { get; set; }
public bool? canLookStory { get; set; } public bool? canLookStory { get; set; }
@ -92,7 +92,7 @@ namespace OF_DL.Entities.Lists
public class Subscribe public class Subscribe
{ {
public object id { get; set; } public object id { get; set; }
public long? userId { get; set; } public int? userId { get; set; }
public int? subscriberId { get; set; } public int? subscriberId { get; set; }
public DateTime? date { get; set; } public DateTime? date { get; set; }
public int? duration { get; set; } public int? duration { get; set; }
@ -160,7 +160,7 @@ namespace OF_DL.Entities.Lists
public class SubscriptionBundle public class SubscriptionBundle
{ {
public long? id { get; set; } public int? id { get; set; }
public string? discount { get; set; } public string? discount { get; set; }
public string? duration { get; set; } public string? duration { get; set; }
public string? price { get; set; } public string? price { get; set; }

View File

@ -43,7 +43,7 @@ namespace OF_DL.Entities.Messages
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -52,7 +52,7 @@ namespace OF_DL.Entities.Messages
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Thumb public class Thumb
@ -60,12 +60,12 @@ namespace OF_DL.Entities.Messages
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class FromUser public class FromUser
{ {
public long? id { get; set; } public int? id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }

View File

@ -17,7 +17,7 @@ namespace OF_DL.Entities.Messages
public string header { get; set; } public string header { get; set; }
public HeaderSize headerSize { get; set; } public HeaderSize headerSize { get; set; }
public HeaderThumbs headerThumbs { get; set; } public HeaderThumbs headerThumbs { get; set; }
public long? id { get; set; } public int? id { get; set; }
public string name { get; set; } public string name { get; set; }
public string username { get; set; } public string username { get; set; }
public bool canLookStory { get; set; } public bool canLookStory { get; set; }
@ -81,7 +81,7 @@ namespace OF_DL.Entities.Messages
{ {
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class SingleMessage public class SingleMessage

View File

@ -20,7 +20,7 @@ public class Post
public string tailMarker { get; set; } public string tailMarker { get; set; }
public class Author public class Author
{ {
public long id { get; set; } public int id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
@ -56,7 +56,7 @@ public class Post
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -65,7 +65,7 @@ public class Post
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Thumb public class Thumb
@ -73,7 +73,7 @@ public class Post
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Hls public class Hls

View File

@ -12,7 +12,7 @@ namespace OF_DL.Entities.Post
public class SinglePost public class SinglePost
{ {
public string responseType { get; set; } public string responseType { get; set; }
public long id { get; set; } public int id { get; set; }
public DateTime postedAt { get; set; } public DateTime postedAt { get; set; }
public string postedAtPrecise { get; set; } public string postedAtPrecise { get; set; }
public object expiredAt { get; set; } public object expiredAt { get; set; }
@ -67,7 +67,7 @@ namespace OF_DL.Entities.Post
public List<object> preview { get; set; } public List<object> preview { get; set; }
public class Author public class Author
{ {
public long id { get; set; } public int id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
@ -85,7 +85,7 @@ namespace OF_DL.Entities.Post
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -94,7 +94,7 @@ namespace OF_DL.Entities.Post
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Thumb public class Thumb
@ -102,7 +102,7 @@ namespace OF_DL.Entities.Post
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Info public class Info
@ -134,7 +134,7 @@ namespace OF_DL.Entities.Post
{ {
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public string url { get; set; } public string url { get; set; }
} }
@ -143,7 +143,7 @@ namespace OF_DL.Entities.Post
public string source { get; set; } public string source { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public int duration { get; set; } public int duration { get; set; }
} }

View File

@ -13,14 +13,17 @@ namespace OF_DL.Entities.Purchased
public List<List> list { get; set; } public List<List> list { get; set; }
public bool hasMore { get; set; } public bool hasMore { get; set; }
public class FromUser public class FromUser
{ {
public long id { get; set; } public int id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
public class Author public class Author
{ {
public long id { get; set; } public int id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
@ -78,5 +81,10 @@ namespace OF_DL.Entities.Purchased
public string hls { get; set; } public string hls { get; set; }
public string dash { get; set; } public string dash { get; set; }
} }
} }
} }

View File

@ -9,8 +9,8 @@ namespace OF_DL.Entities.Stories
{ {
public class Stories public class Stories
{ {
public long id { get; set; } public int id { get; set; }
public long userId { get; set; } public int userId { get; set; }
public bool isWatched { get; set; } public bool isWatched { get; set; }
public bool isReady { get; set; } public bool isReady { get; set; }
public List<Medium> media { get; set; } public List<Medium> media { get; set; }
@ -31,7 +31,7 @@ namespace OF_DL.Entities.Stories
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -51,7 +51,7 @@ namespace OF_DL.Entities.Stories
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public Sources sources { get; set; } public Sources sources { get; set; }
} }
@ -61,7 +61,7 @@ namespace OF_DL.Entities.Stories
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public int duration { get; set; } public int duration { get; set; }
public long size { get; set; } public int size { get; set; }
public Sources sources { get; set; } public Sources sources { get; set; }
} }
@ -81,7 +81,7 @@ namespace OF_DL.Entities.Stories
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public Sources sources { get; set; } public Sources sources { get; set; }
} }
@ -90,7 +90,7 @@ namespace OF_DL.Entities.Stories
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
} }
} }

View File

@ -17,7 +17,7 @@ namespace OF_DL.Entities.Streams
public Counters counters { get; set; } public Counters counters { get; set; }
public class Author public class Author
{ {
public long id { get; set; } public int id { get; set; }
public string _view { get; set; } public string _view { get; set; }
} }
@ -46,7 +46,7 @@ namespace OF_DL.Entities.Streams
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public List<object> sources { get; set; } public List<object> sources { get; set; }
} }
@ -55,7 +55,7 @@ namespace OF_DL.Entities.Streams
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Thumb public class Thumb
@ -63,7 +63,7 @@ namespace OF_DL.Entities.Streams
public string url { get; set; } public string url { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
} }
public class Info public class Info
@ -154,7 +154,7 @@ namespace OF_DL.Entities.Streams
{ {
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public string url { get; set; } public string url { get; set; }
} }
@ -163,7 +163,7 @@ namespace OF_DL.Entities.Streams
public string source { get; set; } public string source { get; set; }
public int width { get; set; } public int width { get; set; }
public int height { get; set; } public int height { get; set; }
public long size { get; set; } public int size { get; set; }
public int duration { get; set; } public int duration { get; set; }
} }

View File

@ -36,7 +36,7 @@ namespace OF_DL.Entities
public string header { get; set; } public string header { get; set; }
public HeaderSize headerSize { get; set; } public HeaderSize headerSize { get; set; }
public HeaderThumbs headerThumbs { get; set; } public HeaderThumbs headerThumbs { get; set; }
public long id { get; set; } public int id { get; set; }
public string name { get; set; } public string name { get; set; }
public string username { get; set; } public string username { get; set; }
public bool? canLookStory { get; set; } public bool? canLookStory { get; set; }
@ -96,7 +96,7 @@ namespace OF_DL.Entities
public class Subscribe public class Subscribe
{ {
public object id { get; set; } public object id { get; set; }
public long? userId { get; set; } public int? userId { get; set; }
public int? subscriberId { get; set; } public int? subscriberId { get; set; }
public DateTime? date { get; set; } public DateTime? date { get; set; }
public int? duration { get; set; } public int? duration { get; set; }

View File

@ -14,7 +14,7 @@ namespace OF_DL.Entities
public string? header { get; set; } public string? header { get; set; }
public HeaderSize headerSize { get; set; } public HeaderSize headerSize { get; set; }
public HeaderThumbs headerThumbs { get; set; } public HeaderThumbs headerThumbs { get; set; }
public long? id { get; set; } public int? id { get; set; }
public string name { get; set; } public string name { get; set; }
public string username { get; set; } public string username { get; set; }
public bool? canLookStory { get; set; } public bool? canLookStory { get; set; }
@ -124,7 +124,7 @@ namespace OF_DL.Entities
public class Subscribe public class Subscribe
{ {
public long? id { get; set; } public long? id { get; set; }
public long? userId { get; set; } public int? userId { get; set; }
public int? subscriberId { get; set; } public int? subscriberId { get; set; }
public DateTime? date { get; set; } public DateTime? date { get; set; }
public int? duration { get; set; } public int? duration { get; set; }

View File

@ -31,8 +31,6 @@ public class APIHelper : IAPIHelper
private readonly Auth auth; private readonly Auth auth;
private static DateTime? cachedDynamicRulesExpiration; private static DateTime? cachedDynamicRulesExpiration;
private static DynamicRules? cachedDynamicRules; private static DynamicRules? cachedDynamicRules;
private const int MaxAttempts = 30;
private const int DelayBetweenAttempts = 3000;
static APIHelper() static APIHelper()
{ {
@ -295,11 +293,11 @@ public class APIHelper : IAPIHelper
} }
public async Task<Dictionary<string, long>?> GetAllSubscriptions(Dictionary<string, string> getParams, string endpoint, bool includeRestricted, IDownloadConfig config) public async Task<Dictionary<string, int>?> GetAllSubscriptions(Dictionary<string, string> getParams, string endpoint, bool includeRestricted, IDownloadConfig config)
{ {
try try
{ {
Dictionary<string, long> users = new(); Dictionary<string, int> users = new();
Subscriptions subscriptions = new(); Subscriptions subscriptions = new();
Log.Debug("Calling GetAllSubscrptions"); Log.Debug("Calling GetAllSubscrptions");
@ -359,7 +357,7 @@ public class APIHelper : IAPIHelper
return null; return null;
} }
public async Task<Dictionary<string, long>?> GetActiveSubscriptions(string endpoint, bool includeRestricted, IDownloadConfig config) public async Task<Dictionary<string, int>?> GetActiveSubscriptions(string endpoint, bool includeRestricted, IDownloadConfig config)
{ {
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
@ -373,7 +371,7 @@ public class APIHelper : IAPIHelper
} }
public async Task<Dictionary<string, long>?> GetExpiredSubscriptions(string endpoint, bool includeRestricted, IDownloadConfig config) public async Task<Dictionary<string, int>?> GetExpiredSubscriptions(string endpoint, bool includeRestricted, IDownloadConfig config)
{ {
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
@ -390,7 +388,7 @@ public class APIHelper : IAPIHelper
} }
public async Task<Dictionary<string, long>> GetLists(string endpoint, IDownloadConfig config) public async Task<Dictionary<string, int>> GetLists(string endpoint, IDownloadConfig config)
{ {
Log.Debug("Calling GetLists"); Log.Debug("Calling GetLists");
@ -404,7 +402,7 @@ public class APIHelper : IAPIHelper
{ "limit", "50" }, { "limit", "50" },
{ "format", "infinite" } { "format", "infinite" }
}; };
Dictionary<string, long> lists = new(); Dictionary<string, int> lists = new();
while (true) while (true)
{ {
string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient());
@ -2067,13 +2065,13 @@ public class APIHelper : IAPIHelper
return null; return null;
} }
public async Task<Dictionary<string, long>> GetPurchasedTabUsers(string endpoint, IDownloadConfig config, Dictionary<string, long> users) public async Task<Dictionary<string, int>> GetPurchasedTabUsers(string endpoint, IDownloadConfig config, Dictionary<string, int> users)
{ {
Log.Debug($"Calling GetPurchasedTabUsers - {endpoint}"); Log.Debug($"Calling GetPurchasedTabUsers - {endpoint}");
try try
{ {
Dictionary<string, long> purchasedTabUsers = new(); Dictionary<string, int> purchasedTabUsers = new();
Purchased purchased = new(); Purchased purchased = new();
int post_limit = 50; int post_limit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
@ -2240,7 +2238,7 @@ public class APIHelper : IAPIHelper
return null; return null;
} }
public async Task<List<PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder, IDownloadConfig config, Dictionary<string, long> users) public async Task<List<PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder, IDownloadConfig config, Dictionary<string, int> users)
{ {
Log.Debug($"Calling GetPurchasedTab - {endpoint}"); Log.Debug($"Calling GetPurchasedTab - {endpoint}");
@ -2676,10 +2674,13 @@ public class APIHelper : IAPIHelper
return DateTime.Now; return DateTime.Now;
} }
public async Task<string> GetDecryptionKeyCDRMProject(Dictionary<string, string> drmHeaders, string licenceURL, string pssh) public async Task<string> GetDecryptionKeyCDRMProject(Dictionary<string, string> drmHeaders, string licenceURL, string pssh)
{ {
Log.Debug("Calling GetDecryptionKey"); Log.Debug("Calling GetDecryptionKey");
const int maxAttempts = 30;
const int delayBetweenAttempts = 3000;
int attempt = 0; int attempt = 0;
try try
@ -2700,7 +2701,7 @@ public class APIHelper : IAPIHelper
Log.Debug($"Posting to CDRM Project: {json}"); Log.Debug($"Posting to CDRM Project: {json}");
while (attempt < MaxAttempts) while (attempt < maxAttempts)
{ {
attempt++; attempt++;
@ -2726,19 +2727,19 @@ public class APIHelper : IAPIHelper
} }
else else
{ {
Log.Debug($"CDRM response status not successful. Retrying... Attempt {attempt} of {MaxAttempts}"); Log.Debug($"CDRM response status not successful. Retrying... Attempt {attempt} of {maxAttempts}");
if (attempt < MaxAttempts) if (attempt < maxAttempts)
{ {
await Task.Delay(DelayBetweenAttempts); await Task.Delay(delayBetweenAttempts);
} }
} }
} }
else else
{ {
Log.Debug($"Status not in CDRM response. Retrying... Attempt {attempt} of {MaxAttempts}"); Log.Debug($"Status not in CDRM response. Retrying... Attempt {attempt} of {maxAttempts}");
if (attempt < MaxAttempts) if (attempt < maxAttempts)
{ {
await Task.Delay(DelayBetweenAttempts); await Task.Delay(delayBetweenAttempts);
} }
} }
} }
@ -2763,10 +2764,11 @@ public class APIHelper : IAPIHelper
{ {
Log.Debug("Calling GetDecryptionOFDL"); Log.Debug("Calling GetDecryptionOFDL");
try try
{ {
string dcValue = string.Empty;
HttpClient client = new(); HttpClient client = new();
int attempt = 0;
OFDLRequest ofdlRequest = new OFDLRequest OFDLRequest ofdlRequest = new OFDLRequest
{ {
@ -2779,27 +2781,17 @@ public class APIHelper : IAPIHelper
Log.Debug($"Posting to ofdl.tools: {json}"); Log.Debug($"Posting to ofdl.tools: {json}");
while (attempt < MaxAttempts) HttpRequestMessage request = new(HttpMethod.Post, "https://ofdl.tools/WV")
{ {
attempt++; Content = new StringContent(json, Encoding.UTF8, "application/json")
};
HttpRequestMessage request = new(HttpMethod.Post, "https://ofdl.tools/WV") using var response = await client.SendAsync(request);
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
};
using var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
continue;
if (response.IsSuccessStatusCode)
{
string body = await response.Content.ReadAsStringAsync(); string body = await response.Content.ReadAsStringAsync();
return body;
if (!body.TrimStart().StartsWith('{'))
return body;
Log.Debug($"Received JSON object instead of string. Retrying... Attempt {attempt} of {MaxAttempts}");
await Task.Delay(DelayBetweenAttempts);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -2813,7 +2805,6 @@ public class APIHelper : IAPIHelper
Log.Error("Inner Exception: {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 null; return null;
} }

View File

@ -135,7 +135,7 @@ namespace OF_DL.Helpers
} }
} }
public async Task CreateUsersDB(Dictionary<string, long> users) public async Task CreateUsersDB(Dictionary<string, int> users)
{ {
try try
{ {
@ -150,7 +150,7 @@ namespace OF_DL.Helpers
} }
Log.Debug("Adding missing creators"); Log.Debug("Adding missing creators");
foreach (KeyValuePair<string, long> user in users) foreach (KeyValuePair<string, int> user in users)
{ {
using (SqliteCommand checkCmd = new($"SELECT user_id, username FROM users WHERE user_id = @userId;", connection)) using (SqliteCommand checkCmd = new($"SELECT user_id, username FROM users WHERE user_id = @userId;", connection))
{ {
@ -190,7 +190,7 @@ namespace OF_DL.Helpers
} }
} }
public async Task CheckUsername(KeyValuePair<string, long> user, string path) public async Task CheckUsername(KeyValuePair<string, int> user, string path)
{ {
try try
{ {
@ -243,7 +243,7 @@ namespace OF_DL.Helpers
} }
} }
public async Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at, long user_id) public async Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at, int user_id)
{ {
try try
{ {

View File

@ -164,7 +164,7 @@ public class DownloadHelper : IDownloadHelper
object? postMedia, object? postMedia,
object? author, object? author,
string username, string username,
Dictionary<string, long> users, Dictionary<string, int> users,
IFileNameHelper fileNameHelper, IFileNameHelper fileNameHelper,
CustomFileNameOption option) CustomFileNameOption option)
{ {
@ -630,36 +630,7 @@ public class DownloadHelper : IDownloadHelper
// break; // break;
//} //}
// Configure ffmpeg log level and optional report file location 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}\"";
bool ffmpegDebugLogging = Log.IsEnabled(Serilog.Events.LogEventLevel.Debug);
string logLevelArgs = ffmpegDebugLogging || downloadConfig.LoggingLevel is LoggingLevel.Verbose or LoggingLevel.Debug
? "-loglevel debug -report"
: downloadConfig.LoggingLevel switch
{
LoggingLevel.Information => "-loglevel info",
LoggingLevel.Warning => "-loglevel warning",
LoggingLevel.Error => "-loglevel error",
LoggingLevel.Fatal => "-loglevel fatal",
_ => string.Empty
};
if (logLevelArgs.Contains("-report", StringComparison.OrdinalIgnoreCase))
{
// Direct ffmpeg report files into the same logs directory Serilog uses (relative to current working directory)
string logDir = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "logs"));
Directory.CreateDirectory(logDir);
string ffReportPath = Path.Combine(logDir, "ffmpeg-%p-%t.log"); // ffmpeg will replace %p/%t
Environment.SetEnvironmentVariable("FFREPORT", $"file={ffReportPath}:level=32");
Log.Debug("FFREPORT enabled at: {FFREPORT} (cwd: {Cwd})", Environment.GetEnvironmentVariable("FFREPORT"), Environment.CurrentDirectory);
}
else
{
Environment.SetEnvironmentVariable("FFREPORT", null);
Log.Debug("FFREPORT disabled (cwd: {Cwd})", Environment.CurrentDirectory);
}
string parameters = $"{logLevelArgs} -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}\"".Trim();
Log.Debug($"Calling FFMPEG with Parameters: {parameters}"); Log.Debug($"Calling FFMPEG with Parameters: {parameters}");
@ -690,7 +661,7 @@ public class DownloadHelper : IDownloadHelper
#endregion #endregion
#region normal posts #region normal posts
public async Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null)
@ -708,7 +679,7 @@ public class DownloadHelper : IDownloadHelper
return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename);
} }
public async Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SinglePost? postInfo, SinglePost.Medium? postMedia, SinglePost.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SinglePost? postInfo, SinglePost.Medium? postMedia, SinglePost.Author? author, Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null)
@ -726,7 +697,7 @@ public class DownloadHelper : IDownloadHelper
return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename);
} }
public async Task<bool> DownloadStreamMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadStreamMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerPost && streamInfo != null && streamInfo?.id is not null && streamInfo?.postedAt is not null) if (downloadConfig.FolderPerPost && streamInfo != null && streamInfo?.id is not null && streamInfo?.postedAt is not null)
@ -746,7 +717,7 @@ public class DownloadHelper : IDownloadHelper
} }
public async Task<bool> DownloadMessageMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Messages.List? messageInfo, Messages.Medium? messageMedia, Messages.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadMessageMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Messages.List? messageInfo, Messages.Medium? messageMedia, Messages.FromUser? fromUser, Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) if (downloadConfig.FolderPerMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null)
@ -764,7 +735,7 @@ public class DownloadHelper : IDownloadHelper
} }
public async Task<bool> DownloadArchivedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Archived.List? messageInfo, Archived.Medium? messageMedia, Archived.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadArchivedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Archived.List? messageInfo, Archived.Medium? messageMedia, Archived.Author? author, Dictionary<string, int> users)
{ {
string path = "/Archived/Posts/Free"; string path = "/Archived/Posts/Free";
Uri uri = new(url); Uri uri = new(url);
@ -783,7 +754,7 @@ public class DownloadHelper : IDownloadHelper
return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, filename); return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, filename);
} }
public async Task<bool> DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, Purchased.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, Purchased.FromUser? fromUser, Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null)
@ -800,7 +771,7 @@ public class DownloadHelper : IDownloadHelper
return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename);
} }
public async Task<bool> DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null)
@ -826,7 +797,7 @@ public class DownloadHelper : IDownloadHelper
Purchased.List? messageInfo, Purchased.List? messageInfo,
Medium? messageMedia, Medium? messageMedia,
Purchased.FromUser? fromUser, Purchased.FromUser? fromUser,
Dictionary<string, long> users) Dictionary<string, int> users)
{ {
string path; string path;
if (downloadConfig.FolderPerPaidPost && messageInfo != null && messageInfo?.id is not null && messageInfo?.postedAt is not null) if (downloadConfig.FolderPerPaidPost && messageInfo != null && messageInfo?.id is not null && messageInfo?.postedAt is not null)
@ -994,22 +965,12 @@ public class DownloadHelper : IDownloadHelper
private void OnError(object sender, ConversionErrorEventArgs e) private void OnError(object sender, ConversionErrorEventArgs e)
{ {
// Guard all fields to avoid NullReference exceptions from FFmpeg.NET Log.Debug("[{0} => {1}]: Error: {2}\n{3}", e.Input.Name, e.Output.Name, e.Exception.ExitCode, e.Exception.InnerException);
var input = e?.Input?.Name ?? "<none>";
var output = e?.Output?.Name ?? "<none>";
var exitCode = e?.Exception?.ExitCode.ToString() ?? "<unknown>";
var message = e?.Exception?.Message ?? "<no message>";
var inner = e?.Exception?.InnerException?.Message ?? "<no inner>";
Log.Error("FFmpeg failed. Input={Input} Output={Output} ExitCode={ExitCode} Message={Message} Inner={Inner}",
input, output, exitCode, message, inner);
_completionSource?.TrySetResult(false); _completionSource?.TrySetResult(false);
} }
#region drm posts #region drm posts
public async Task<bool> DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Messages.List? messageInfo, Messages.Medium? messageMedia, Messages.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Messages.List? messageInfo, Messages.Medium? messageMedia, Messages.FromUser? fromUser, Dictionary<string, int> users)
{ {
try try
{ {
@ -1117,7 +1078,7 @@ public class DownloadHelper : IDownloadHelper
} }
public async Task<bool> DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, Purchased.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, Purchased.FromUser? fromUser, Dictionary<string, int> users)
{ {
try try
{ {
@ -1223,7 +1184,7 @@ public class DownloadHelper : IDownloadHelper
return false; return false;
} }
public async Task<bool> DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, int> users)
{ {
try try
{ {
@ -1330,7 +1291,7 @@ public class DownloadHelper : IDownloadHelper
} }
public async Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary<string, int> users)
{ {
try try
{ {
@ -1435,7 +1396,7 @@ public class DownloadHelper : IDownloadHelper
} }
return false; return false;
} }
public async Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, SinglePost postInfo, SinglePost.Medium postMedia, SinglePost.Author author, Dictionary<string, long> users) public async Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, SinglePost postInfo, SinglePost.Medium postMedia, SinglePost.Author author, Dictionary<string, int> users)
{ {
try try
{ {
@ -1540,7 +1501,7 @@ public class DownloadHelper : IDownloadHelper
} }
return false; return false;
} }
public async Task<bool> DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary<string, int> users)
{ {
try try
{ {
@ -1646,7 +1607,7 @@ public class DownloadHelper : IDownloadHelper
return false; return false;
} }
public async Task<bool> DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? postInfo, Medium? postMedia, Purchased.FromUser? fromUser, Dictionary<string, long> users) public async Task<bool> DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? postInfo, Medium? postMedia, Purchased.FromUser? fromUser, Dictionary<string, int> users)
{ {
try try
{ {
@ -1754,7 +1715,7 @@ public class DownloadHelper : IDownloadHelper
} }
public async Task<bool> DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Archived.List? postInfo, Archived.Medium? postMedia, Archived.Author? author, Dictionary<string, long> users) public async Task<bool> DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Archived.List? postInfo, Archived.Medium? postMedia, Archived.Author? author, Dictionary<string, int> users)
{ {
try try
{ {

View File

@ -18,7 +18,7 @@ namespace OF_DL.Helpers
this.auth = auth; this.auth = auth;
} }
public async Task<Dictionary<string, string>> GetFilename(object obj1, object obj2, object obj3, List<string> selectedProperties, string username, Dictionary<string, long> users = null) public async Task<Dictionary<string, string>> GetFilename(object obj1, object obj2, object obj3, List<string> selectedProperties, string username, Dictionary<string, int> users = null)
{ {
Dictionary<string, string> values = new(); Dictionary<string, string> values = new();
Type type1 = obj1.GetType(); Type type1 = obj1.GetType();

View File

@ -16,7 +16,7 @@ namespace OF_DL.Helpers
Task<string> GetDecryptionKeyCDM(Dictionary<string, string> drmHeaders, string licenceURL, string pssh); Task<string> GetDecryptionKeyCDM(Dictionary<string, string> drmHeaders, string licenceURL, string pssh);
Task<DateTime> GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp); Task<DateTime> GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp);
Task<string> GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp); Task<string> GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp);
Task<Dictionary<string, long>> GetLists(string endpoint, IDownloadConfig config); Task<Dictionary<string, int>> GetLists(string endpoint, IDownloadConfig config);
Task<List<string>> GetListUsers(string endpoint, IDownloadConfig config); Task<List<string>> GetListUsers(string endpoint, IDownloadConfig config);
Task<Dictionary<long, string>> GetMedia(MediaType mediatype, string endpoint, string? username, string folder, IDownloadConfig config, List<long> paid_post_ids); Task<Dictionary<long, string>> GetMedia(MediaType mediatype, string endpoint, string? username, string folder, IDownloadConfig config, List<long> paid_post_ids);
Task<PaidPostCollection> GetPaidPosts(string endpoint, string folder, string username, IDownloadConfig config, List<long> paid_post_ids, StatusContext ctx); Task<PaidPostCollection> GetPaidPosts(string endpoint, string folder, string username, IDownloadConfig config, List<long> paid_post_ids, StatusContext ctx);
@ -26,13 +26,13 @@ namespace OF_DL.Helpers
Task<ArchivedCollection> GetArchived(string endpoint, string folder, IDownloadConfig config, StatusContext ctx); Task<ArchivedCollection> GetArchived(string endpoint, string folder, IDownloadConfig config, StatusContext ctx);
Task<MessageCollection> GetMessages(string endpoint, string folder, IDownloadConfig config, StatusContext ctx); Task<MessageCollection> GetMessages(string endpoint, string folder, IDownloadConfig config, StatusContext ctx);
Task<PaidMessageCollection> GetPaidMessages(string endpoint, string folder, string username, IDownloadConfig config, StatusContext ctx); Task<PaidMessageCollection> GetPaidMessages(string endpoint, string folder, string username, IDownloadConfig config, StatusContext ctx);
Task<Dictionary<string, long>> GetPurchasedTabUsers(string endpoint, IDownloadConfig config, Dictionary<string, long> users); Task<Dictionary<string, int>> GetPurchasedTabUsers(string endpoint, IDownloadConfig config, Dictionary<string, int> users);
Task<List<PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder, IDownloadConfig config, Dictionary<string, long> users); Task<List<PurchasedTabCollection>> GetPurchasedTab(string endpoint, string folder, IDownloadConfig config, Dictionary<string, int> users);
Task<User> GetUserInfo(string endpoint); Task<User> GetUserInfo(string endpoint);
Task<JObject> GetUserInfoById(string endpoint); Task<JObject> GetUserInfoById(string endpoint);
Dictionary<string, string> GetDynamicHeaders(string path, string queryParam); Dictionary<string, string> GetDynamicHeaders(string path, string queryParam);
Task<Dictionary<string, long>> GetActiveSubscriptions(string endpoint, bool includeRestrictedSubscriptions, IDownloadConfig config); Task<Dictionary<string, int>> GetActiveSubscriptions(string endpoint, bool includeRestrictedSubscriptions, IDownloadConfig config);
Task<Dictionary<string, long>> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions, IDownloadConfig config); Task<Dictionary<string, int>> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions, IDownloadConfig config);
Task<string> GetDecryptionKeyOFDL(Dictionary<string, string> drmHeaders, string licenceURL, string pssh); Task<string> GetDecryptionKeyOFDL(Dictionary<string, string> drmHeaders, string licenceURL, string pssh);
} }
} }

View File

@ -2,12 +2,12 @@ namespace OF_DL.Helpers
{ {
public interface IDBHelper public interface IDBHelper
{ {
Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at, long user_id); Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at, int user_id);
Task AddPost(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at); Task AddPost(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at);
Task AddStory(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at); Task AddStory(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at);
Task CreateDB(string folder); Task CreateDB(string folder);
Task CreateUsersDB(Dictionary<string, long> users); Task CreateUsersDB(Dictionary<string, int> users);
Task CheckUsername(KeyValuePair<string, long> user, string path); Task CheckUsername(KeyValuePair<string, int> user, string path);
Task AddMedia(string folder, long media_id, long post_id, string link, string? directory, string? filename, long? size, string api_type, string media_type, bool preview, bool downloaded, DateTime? created_at); Task AddMedia(string folder, long media_id, long post_id, string link, string? directory, string? filename, long? size, string api_type, string media_type, bool preview, bool downloaded, DateTime? created_at);
Task UpdateMedia(string folder, long media_id, string api_type, string directory, string filename, long size, bool downloaded, DateTime created_at); Task UpdateMedia(string folder, long media_id, string api_type, string directory, string filename, long size, bool downloaded, DateTime created_at);
Task<long> GetStoredFileSize(string folder, long media_id, string api_type); Task<long> GetStoredFileSize(string folder, long media_id, string api_type);

View File

@ -12,25 +12,25 @@ namespace OF_DL.Helpers
public interface IDownloadHelper public interface IDownloadHelper
{ {
Task<long> CalculateTotalFileSize(List<string> urls); Task<long> CalculateTotalFileSize(List<string> urls);
Task<bool> DownloadArchivedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Archived.List messageInfo, Archived.Medium messageMedia, Archived.Author author, Dictionary<string, long> users); Task<bool> DownloadArchivedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Archived.List messageInfo, Archived.Medium messageMedia, Archived.Author author, Dictionary<string, int> users);
Task<bool> DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Archived.List postInfo, Archived.Medium postMedia, Archived.Author author, Dictionary<string, long> users); Task<bool> DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Archived.List postInfo, Archived.Medium postMedia, Archived.Author author, Dictionary<string, int> users);
Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, SinglePost postInfo, SinglePost.Medium postMedia, SinglePost.Author author, Dictionary<string, long> users); Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, SinglePost postInfo, SinglePost.Medium postMedia, SinglePost.Author author, Dictionary<string, int> users);
Task DownloadAvatarHeader(string? avatarUrl, string? headerUrl, string folder, string username); Task DownloadAvatarHeader(string? avatarUrl, string? headerUrl, string folder, string username);
Task<bool> DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Messages.List messageInfo, Messages.Medium messageMedia, Messages.FromUser fromUser, Dictionary<string, long> users); Task<bool> DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Messages.List messageInfo, Messages.Medium messageMedia, Messages.FromUser fromUser, Dictionary<string, int> users);
Task<bool> DownloadMessageMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Messages.List messageInfo, Messages.Medium messageMedia, Messages.FromUser fromUser, Dictionary<string, long> users); Task<bool> DownloadMessageMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Messages.List messageInfo, Messages.Medium messageMedia, Messages.FromUser fromUser, Dictionary<string, int> users);
Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Post.List postInfo, Post.Medium postMedia, Post.Author author, Dictionary<string, long> users); Task<bool> DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Post.List postInfo, Post.Medium postMedia, Post.Author author, Dictionary<string, int> users);
Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary<string, long> users); Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary<string, int> users);
Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SinglePost? postInfo, SinglePost.Medium? postMedia, SinglePost.Author? author, Dictionary<string, long> users); Task<bool> DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SinglePost? postInfo, SinglePost.Medium? postMedia, SinglePost.Author? author, Dictionary<string, int> users);
Task<bool> DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary<string, long> users); Task<bool> DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary<string, int> users);
Task<bool> DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, long> users); Task<bool> DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, int> users);
Task<bool> DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary<string, long> users); Task<bool> DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary<string, int> users);
Task<bool> DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, long> users); Task<bool> DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary<string, int> users);
Task<bool> DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List postInfo, Medium postMedia, Purchased.FromUser fromUser, Dictionary<string, long> users); Task<bool> DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List postInfo, Medium postMedia, Purchased.FromUser fromUser, Dictionary<string, int> users);
Task<bool> DownloadPurchasedPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary<string, long> users); Task<bool> DownloadPurchasedPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary<string, int> users);
Task<bool> DownloadStoryMedia(string url, string folder, long media_id, string api_type, ProgressTask task); Task<bool> DownloadStoryMedia(string url, string folder, long media_id, string api_type, ProgressTask task);
Task<bool> DownloadStreamMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary<string, long> users); Task<bool> DownloadStreamMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary<string, int> users);
Task<bool> DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Streams.List streamInfo, Streams.Medium streamMedia, Streams.Author author, Dictionary<string, long> users); Task<bool> DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Streams.List streamInfo, Streams.Medium streamMedia, Streams.Author author, Dictionary<string, int> users);
} }
} }

View File

@ -3,6 +3,6 @@ namespace OF_DL.Helpers
public interface IFileNameHelper public interface IFileNameHelper
{ {
Task<string> BuildFilename(string fileFormat, Dictionary<string, string> values); Task<string> BuildFilename(string fileFormat, Dictionary<string, string> values);
Task<Dictionary<string, string>> GetFilename(object obj1, object obj2, object obj3, List<string> selectedProperties, string username, Dictionary<string, long> users = null); Task<Dictionary<string, string>> GetFilename(object obj1, object obj2, object obj3, List<string> selectedProperties, string username, Dictionary<string, int> users = null);
} }
} }

View File

@ -6,15 +6,14 @@ namespace OF_DL.Helpers;
public static class VersionHelper public static class VersionHelper
{ {
private static readonly HttpClient httpClient = new HttpClient(); public static string? GetLatestReleaseTag()
private const string url = "https://git.ofdl.tools/api/v1/repos/sim0n00ps/OF-DL/releases/latest";
public static async Task<string?> GetLatestReleaseTag(CancellationToken cancellationToken = default)
{ {
Log.Debug("Calling GetLatestReleaseTag"); Log.Debug("Calling GetLatestReleaseTag");
try try
{ {
var response = await httpClient.GetAsync(url, cancellationToken); HttpClient client = new();
HttpRequestMessage request = new(HttpMethod.Get, "https://git.ofdl.tools/api/v1/repos/sim0n00ps/OF-DL/releases/latest");
using var response = client.Send(request);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
@ -22,7 +21,7 @@ public static class VersionHelper
return null; return null;
} }
var body = await response.Content.ReadAsStringAsync(); var body = response.Content.ReadAsStringAsync().Result;
Log.Debug("GetLatestReleaseTag API Response: "); Log.Debug("GetLatestReleaseTag API Response: ");
Log.Debug(body); Log.Debug(body);
@ -37,10 +36,6 @@ public static class VersionHelper
return versionCheckResponse.TagName; return versionCheckResponse.TagName;
} }
catch (OperationCanceledException)
{
throw; // Rethrow timeout exceptions to be handled by the caller
}
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace);

View File

@ -116,8 +116,6 @@ public class Program
.CreateLogger(); .CreateLogger();
AnsiConsole.Write(new FigletText("Welcome to OF-DL").Color(Color.Red)); AnsiConsole.Write(new FigletText("Welcome to OF-DL").Color(Color.Red));
AnsiConsole.Markup("Documentation: [link]https://docs.ofdl.tools/[/]\n");
AnsiConsole.Markup("Discord server: [link]https://discord.com/invite/6bUW8EJ53j[/]\n\n");
//Remove config.json and convert to config.conf //Remove config.json and convert to config.conf
if (File.Exists("config.json")) if (File.Exists("config.json"))
@ -131,10 +129,6 @@ public class Program
if (jsonConfig != null) if (jsonConfig != null)
{ {
var hoconConfig = new StringBuilder(); var hoconConfig = new StringBuilder();
hoconConfig.AppendLine("# Auth");
hoconConfig.AppendLine("Auth {");
hoconConfig.AppendLine($" DisableBrowserAuth = \"{jsonConfig.DisableBrowserAuth.ToString().ToLower()}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# External Tools"); hoconConfig.AppendLine("# External Tools");
hoconConfig.AppendLine("External {"); hoconConfig.AppendLine("External {");
hoconConfig.AppendLine($" FFmpegPath = \"{jsonConfig.FFmpegPath}\""); hoconConfig.AppendLine($" FFmpegPath = \"{jsonConfig.FFmpegPath}\"");
@ -259,7 +253,7 @@ public class Program
config = new Entities.Config config = new Entities.Config
{ {
//Auth //Auth
DisableBrowserAuth = hoconConfig.GetBoolean("Auth.DisableBrowserAuth"), DisableBrowserAuth = hoconConfig.GetBoolean("DisableBrowserAuth"),
// FFmpeg Settings // FFmpeg Settings
FFmpegPath = hoconConfig.GetString("External.FFmpegPath"), FFmpegPath = hoconConfig.GetString("External.FFmpegPath"),
@ -379,9 +373,7 @@ public class Program
Entities.Config jsonConfig = new Entities.Config(); Entities.Config jsonConfig = new Entities.Config();
var hoconConfig = new StringBuilder(); var hoconConfig = new StringBuilder();
hoconConfig.AppendLine("# Auth"); hoconConfig.AppendLine("# Auth");
hoconConfig.AppendLine("Auth {"); hoconConfig.AppendLine($"DisableBrowserAuth = {jsonConfig.DisableBrowserAuth.ToString().ToLower()}");
hoconConfig.AppendLine($" DisableBrowserAuth = \"{jsonConfig.DisableBrowserAuth.ToString().ToLower()}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# External Tools"); hoconConfig.AppendLine("# External Tools");
hoconConfig.AppendLine("External {"); hoconConfig.AppendLine("External {");
hoconConfig.AppendLine($" FFmpegPath = \"{jsonConfig.FFmpegPath}\""); hoconConfig.AppendLine($" FFmpegPath = \"{jsonConfig.FFmpegPath}\"");
@ -534,50 +526,36 @@ public class Program
// Only run the version check if not in DEBUG mode // Only run the version check if not in DEBUG mode
#if !DEBUG #if !DEBUG
Version localVersion = Assembly.GetEntryAssembly()?.GetName().Version; //Only tested with numeric values. Version localVersion = Assembly.GetEntryAssembly()?.GetName().Version; //Only tested with numeric values.
String? latestReleaseTag = VersionHelper.GetLatestReleaseTag();
// Create a cancellation token with 30 second timeout if (latestReleaseTag == null)
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); {
String? latestReleaseTag = null; AnsiConsole.Markup("[yellow]Failed to verify that OF-DL is up-to-date.\n[/]");
Log.Error("Failed to get the latest release tag.");
}
else
{
Version latestGiteaRelease = new Version(latestReleaseTag.Replace("OFDLV", ""));
try // Compare the Versions
{ int versionComparison = localVersion.CompareTo(latestGiteaRelease);
latestReleaseTag = await VersionHelper.GetLatestReleaseTag(cts.Token); if (versionComparison < 0)
} {
catch (OperationCanceledException) // The version on GitHub is more up to date than this local release.
{ AnsiConsole.Markup("[red]You are running OF-DL version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}\n[/]");
AnsiConsole.Markup("[yellow]Version check timed out after 30 seconds.\n[/]"); AnsiConsole.Markup("[red]Please update to the current release, " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}: [link]https://git.ofdl.tools/sim0n00ps/OF-DL/releases[/]\n[/]");
Log.Warning("Version check timed out after 30 seconds"); Log.Debug("Detected outdated client running version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}");
latestReleaseTag = null; Log.Debug("Latest release version " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}");
} }
else
if (latestReleaseTag == null) {
{ // This local version is greater than the release version on GitHub.
AnsiConsole.Markup("[yellow]Failed to verify that OF-DL is up-to-date.\n[/]"); AnsiConsole.Markup("[green]You are running OF-DL version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}\n[/]");
Log.Error("Failed to get the latest release tag."); AnsiConsole.Markup("[green]Latest Release version: " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}\n[/]");
} Log.Debug("Detected client running version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}");
else Log.Debug("Latest release version " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}");
{ }
Version latestGiteaRelease = new Version(latestReleaseTag.Replace("OFDLV", "")); }
// Compare the Versions
int versionComparison = localVersion.CompareTo(latestGiteaRelease);
if (versionComparison < 0)
{
// The version on GitHub is more up to date than this local release.
AnsiConsole.Markup("[red]You are running OF-DL version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}\n[/]");
AnsiConsole.Markup("[red]Please update to the current release, " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}: [link=https://git.ofdl.tools/sim0n00ps/OF-DL/releases]https://git.ofdl.tools/sim0n00ps/OF-DL/releases[/]\n[/]");
Log.Debug("Detected outdated client running version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}");
Log.Debug("Latest release version " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}");
}
else
{
// This local version is greater than the release version on GitHub.
AnsiConsole.Markup("[green]You are running OF-DL version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}\n[/]");
AnsiConsole.Markup("[green]Latest Release version: " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}\n[/]");
Log.Debug("Detected client running version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}");
Log.Debug("Latest release version " + $"{latestGiteaRelease.Major}.{latestGiteaRelease.Minor}.{latestGiteaRelease.Build}");
}
}
#else #else
AnsiConsole.Markup("[yellow]Running in Debug/Local mode. Version check skipped.\n[/]"); AnsiConsole.Markup("[yellow]Running in Debug/Local mode. Version check skipped.\n[/]");
@ -770,61 +748,6 @@ public class Program
{ {
config.FFmpegPath = config.FFmpegPath.Replace(@"\", @"\\"); config.FFmpegPath = config.FFmpegPath.Replace(@"\", @"\\");
} }
// Get FFmpeg version
try
{
var processStartInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = config.FFmpegPath,
Arguments = "-version",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using (var process = System.Diagnostics.Process.Start(processStartInfo))
{
if (process != null)
{
string output = await process.StandardOutput.ReadToEndAsync();
await process.WaitForExitAsync();
// Log full output
Log.Information("FFmpeg version output:\n{Output}", output);
// Parse first line for console output
string firstLine = output.Split('\n')[0].Trim();
if (firstLine.StartsWith("ffmpeg version"))
{
// Extract version string (text between "ffmpeg version " and " Copyright")
int versionStart = "ffmpeg version ".Length;
int copyrightIndex = firstLine.IndexOf(" Copyright");
if (copyrightIndex > versionStart)
{
string version = firstLine.Substring(versionStart, copyrightIndex - versionStart);
AnsiConsole.Markup($"[green]ffmpeg version detected as {version}[/]\n");
}
else
{
// Fallback if Copyright not found
string version = firstLine.Substring(versionStart);
AnsiConsole.Markup($"[green]ffmpeg version detected as {version}[/]\n");
}
}
else
{
AnsiConsole.Markup($"[yellow]ffmpeg version could not be parsed[/]\n");
}
}
}
}
catch (Exception ex)
{
Log.Warning(ex, "Failed to get FFmpeg version");
AnsiConsole.Markup($"[yellow]Could not retrieve ffmpeg version[/]\n");
}
} }
else else
{ {
@ -927,12 +850,12 @@ public class Program
do do
{ {
DateTime startTime = DateTime.Now; DateTime startTime = DateTime.Now;
Dictionary<string, long> users = new(); Dictionary<string, int> users = new();
Dictionary<string, long> activeSubs = await m_ApiHelper.GetActiveSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config); Dictionary<string, int> activeSubs = await m_ApiHelper.GetActiveSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config);
Log.Debug("Subscriptions: "); Log.Debug("Subscriptions: ");
foreach (KeyValuePair<string, long> activeSub in activeSubs) foreach (KeyValuePair<string, int> activeSub in activeSubs)
{ {
if (!users.ContainsKey(activeSub.Key)) if (!users.ContainsKey(activeSub.Key))
{ {
@ -944,8 +867,8 @@ public class Program
{ {
Log.Debug("Inactive Subscriptions: "); Log.Debug("Inactive Subscriptions: ");
Dictionary<string, long> expiredSubs = await m_ApiHelper.GetExpiredSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config); Dictionary<string, int> expiredSubs = await m_ApiHelper.GetExpiredSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config);
foreach (KeyValuePair<string, long> expiredSub in expiredSubs) foreach (KeyValuePair<string, int> expiredSub in expiredSubs)
{ {
if (!users.ContainsKey(expiredSub.Key)) if (!users.ContainsKey(expiredSub.Key))
{ {
@ -955,7 +878,7 @@ public class Program
} }
} }
Dictionary<string, long> lists = await m_ApiHelper.GetLists("/lists", Config); Dictionary<string, int> lists = await m_ApiHelper.GetLists("/lists", Config);
// Remove users from the list if they are in the ignored list // Remove users from the list if they are in the ignored list
if (!string.IsNullOrEmpty(Config.IgnoredUsersListName)) if (!string.IsNullOrEmpty(Config.IgnoredUsersListName))
@ -973,28 +896,28 @@ public class Program
} }
await dBHelper.CreateUsersDB(users); await dBHelper.CreateUsersDB(users);
KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP; KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP;
if(Config.NonInteractiveMode && Config.NonInteractiveModePurchasedTab) if(Config.NonInteractiveMode && Config.NonInteractiveModePurchasedTab)
{ {
hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, long>>(true, new Dictionary<string, long> { { "PurchasedTab", 0 } }); hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, int>>(true, new Dictionary<string, int> { { "PurchasedTab", 0 } });
} }
else if (Config.NonInteractiveMode && string.IsNullOrEmpty(Config.NonInteractiveModeListName)) else if (Config.NonInteractiveMode && string.IsNullOrEmpty(Config.NonInteractiveModeListName))
{ {
hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, long>>(true, users); hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, int>>(true, users);
} }
else if (Config.NonInteractiveMode && !string.IsNullOrEmpty(Config.NonInteractiveModeListName)) else if (Config.NonInteractiveMode && !string.IsNullOrEmpty(Config.NonInteractiveModeListName))
{ {
var listId = lists[Config.NonInteractiveModeListName]; var listId = lists[Config.NonInteractiveModeListName];
var listUsernames = await m_ApiHelper.GetListUsers($"/lists/{listId}/users", Config) ?? []; var listUsernames = await m_ApiHelper.GetListUsers($"/lists/{listId}/users", Config) ?? [];
var selectedUsers = users.Where(x => listUsernames.Contains(x.Key)).Distinct().ToDictionary(x => x.Key, x => x.Value); var selectedUsers = users.Where(x => listUsernames.Contains(x.Key)).Distinct().ToDictionary(x => x.Key, x => x.Value);
hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, long>>(true, selectedUsers); hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, int>>(true, selectedUsers);
} }
else else
{ {
var userSelectionResult = await HandleUserSelection(m_ApiHelper, Config, users, lists); var userSelectionResult = await HandleUserSelection(m_ApiHelper, Config, users, lists);
Config = userSelectionResult.updatedConfig; Config = userSelectionResult.updatedConfig;
hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, long>>(userSelectionResult.IsExit, userSelectionResult.selectedUsers); hasSelectedUsersKVP = new KeyValuePair<bool, Dictionary<string, int>>(userSelectionResult.IsExit, userSelectionResult.selectedUsers);
} }
if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("SinglePost")) if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("SinglePost"))
@ -1060,9 +983,9 @@ public class Program
} }
else if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("PurchasedTab")) else if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("PurchasedTab"))
{ {
Dictionary<string, long> purchasedTabUsers = await m_ApiHelper.GetPurchasedTabUsers("/posts/paid/all", Config, users); Dictionary<string, int> purchasedTabUsers = await m_ApiHelper.GetPurchasedTabUsers("/posts/paid/all", Config, users);
AnsiConsole.Markup($"[red]Checking folders for Users in Purchased Tab\n[/]"); AnsiConsole.Markup($"[red]Checking folders for Users in Purchased Tab\n[/]");
foreach (KeyValuePair<string, long> user in purchasedTabUsers) foreach (KeyValuePair<string, int> user in purchasedTabUsers)
{ {
string path = ""; string path = "";
if (!string.IsNullOrEmpty(Config.DownloadPath)) if (!string.IsNullOrEmpty(Config.DownloadPath))
@ -1220,7 +1143,7 @@ public class Program
else if (hasSelectedUsersKVP.Key && !hasSelectedUsersKVP.Value.ContainsKey("ConfigChanged")) else if (hasSelectedUsersKVP.Key && !hasSelectedUsersKVP.Value.ContainsKey("ConfigChanged"))
{ {
//Iterate over each user in the list of users //Iterate over each user in the list of users
foreach (KeyValuePair<string, long> user in hasSelectedUsersKVP.Value) foreach (KeyValuePair<string, int> user in hasSelectedUsersKVP.Value)
{ {
int paidPostCount = 0; int paidPostCount = 0;
int postCount = 0; int postCount = 0;
@ -1378,7 +1301,7 @@ public class Program
return combinedConfig; return combinedConfig;
} }
private static async Task<int> DownloadPaidMessages(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, KeyValuePair<string, long> user, int paidMessagesCount, string path) private static async Task<int> DownloadPaidMessages(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, KeyValuePair<string, int> user, int paidMessagesCount, string path)
{ {
Log.Debug($"Calling DownloadPaidMessages - {user.Key}"); Log.Debug($"Calling DownloadPaidMessages - {user.Key}");
@ -1511,7 +1434,7 @@ public class Program
return paidMessagesCount; return paidMessagesCount;
} }
private static async Task<int> DownloadMessages(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, KeyValuePair<string, long> user, int messagesCount, string path) private static async Task<int> DownloadMessages(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, KeyValuePair<string, int> user, int messagesCount, string path)
{ {
Log.Debug($"Calling DownloadMessages - {user.Key}"); Log.Debug($"Calling DownloadMessages - {user.Key}");
@ -1644,7 +1567,7 @@ public class Program
return messagesCount; return messagesCount;
} }
private static async Task<int> DownloadHighlights(IDownloadContext downloadContext, KeyValuePair<string, long> user, int highlightsCount, string path) private static async Task<int> DownloadHighlights(IDownloadContext downloadContext, KeyValuePair<string, int> user, int highlightsCount, string path)
{ {
Log.Debug($"Calling DownloadHighlights - {user.Key}"); Log.Debug($"Calling DownloadHighlights - {user.Key}");
@ -1701,7 +1624,7 @@ public class Program
return highlightsCount; return highlightsCount;
} }
private static async Task<int> DownloadStories(IDownloadContext downloadContext, KeyValuePair<string, long> user, int storiesCount, string path) private static async Task<int> DownloadStories(IDownloadContext downloadContext, KeyValuePair<string, int> user, int storiesCount, string path)
{ {
Log.Debug($"Calling DownloadStories - {user.Key}"); Log.Debug($"Calling DownloadStories - {user.Key}");
@ -1758,7 +1681,7 @@ public class Program
return storiesCount; return storiesCount;
} }
private static async Task<int> DownloadArchived(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, KeyValuePair<string, long> user, int archivedCount, string path) private static async Task<int> DownloadArchived(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, KeyValuePair<string, int> user, int archivedCount, string path)
{ {
Log.Debug($"Calling DownloadArchived - {user.Key}"); Log.Debug($"Calling DownloadArchived - {user.Key}");
@ -1891,7 +1814,7 @@ public class Program
return archivedCount; return archivedCount;
} }
private static async Task<int> DownloadFreePosts(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, KeyValuePair<string, long> user, int postCount, string path) private static async Task<int> DownloadFreePosts(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, KeyValuePair<string, int> user, int postCount, string path)
{ {
Log.Debug($"Calling DownloadFreePosts - {user.Key}"); Log.Debug($"Calling DownloadFreePosts - {user.Key}");
@ -2031,7 +1954,7 @@ public class Program
return postCount; return postCount;
} }
private static async Task<int> DownloadPaidPosts(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, KeyValuePair<string, long> user, int paidPostCount, string path) private static async Task<int> DownloadPaidPosts(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, KeyValuePair<string, int> user, int paidPostCount, string path)
{ {
Log.Debug($"Calling DownloadPaidPosts - {user.Key}"); Log.Debug($"Calling DownloadPaidPosts - {user.Key}");
@ -2164,7 +2087,7 @@ public class Program
return paidPostCount; return paidPostCount;
} }
private static async Task<int> DownloadPaidPostsPurchasedTab(IDownloadContext downloadContext, PaidPostCollection purchasedPosts, KeyValuePair<string, long> user, int paidPostCount, string path, Dictionary<string, long> users) private static async Task<int> DownloadPaidPostsPurchasedTab(IDownloadContext downloadContext, PaidPostCollection purchasedPosts, KeyValuePair<string, int> user, int paidPostCount, string path, Dictionary<string, int> users)
{ {
int oldPaidPostCount = 0; int oldPaidPostCount = 0;
int newPaidPostCount = 0; int newPaidPostCount = 0;
@ -2288,7 +2211,7 @@ public class Program
return paidPostCount; return paidPostCount;
} }
private static async Task<int> DownloadPaidMessagesPurchasedTab(IDownloadContext downloadContext, PaidMessageCollection paidMessageCollection, KeyValuePair<string, long> user, int paidMessagesCount, string path, Dictionary<string, long> users) private static async Task<int> DownloadPaidMessagesPurchasedTab(IDownloadContext downloadContext, PaidMessageCollection paidMessageCollection, KeyValuePair<string, int> user, int paidMessagesCount, string path, Dictionary<string, int> users)
{ {
int oldPaidMessagesCount = 0; int oldPaidMessagesCount = 0;
int newPaidMessagesCount = 0; int newPaidMessagesCount = 0;
@ -2413,7 +2336,7 @@ public class Program
return paidMessagesCount; return paidMessagesCount;
} }
private static async Task<int> DownloadStreams(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, KeyValuePair<string, long> user, int streamsCount, string path) private static async Task<int> DownloadStreams(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, KeyValuePair<string, int> user, int streamsCount, string path)
{ {
Log.Debug($"Calling DownloadStreams - {user.Key}"); Log.Debug($"Calling DownloadStreams - {user.Key}");
@ -2552,7 +2475,7 @@ public class Program
return streamsCount; return streamsCount;
} }
private static async Task<int> DownloadPaidMessage(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, long>> hasSelectedUsersKVP, string username, int paidMessagesCount, string path, long message_id) private static async Task<int> DownloadPaidMessage(IDownloadContext downloadContext, KeyValuePair<bool, Dictionary<string, int>> hasSelectedUsersKVP, string username, int paidMessagesCount, string path, long message_id)
{ {
Log.Debug($"Calling DownloadPaidMessage - {username}"); Log.Debug($"Calling DownloadPaidMessage - {username}");
@ -2682,7 +2605,7 @@ public class Program
return paidMessagesCount; return paidMessagesCount;
} }
private static async Task DownloadSinglePost(IDownloadContext downloadContext, long post_id, string path, Dictionary<string, long> users) private static async Task DownloadSinglePost(IDownloadContext downloadContext, long post_id, string path, Dictionary<string, int> users)
{ {
Log.Debug($"Calling DownloadSinglePost - {post_id.ToString()}"); Log.Debug($"Calling DownloadSinglePost - {post_id.ToString()}");
@ -2800,10 +2723,10 @@ public class Program
} }
} }
public static async Task<(bool IsExit, Dictionary<string, long>? selectedUsers, Entities.Config? updatedConfig)> HandleUserSelection(APIHelper apiHelper, Entities.Config currentConfig, Dictionary<string, long> users, Dictionary<string, long> lists) public static async Task<(bool IsExit, Dictionary<string, int>? selectedUsers, Entities.Config? updatedConfig)> HandleUserSelection(APIHelper apiHelper, Entities.Config currentConfig, Dictionary<string, int> users, Dictionary<string, int> lists)
{ {
bool hasSelectedUsers = false; bool hasSelectedUsers = false;
Dictionary<string, long> selectedUsers = new Dictionary<string, long>(); Dictionary<string, int> selectedUsers = new Dictionary<string, int>();
while (!hasSelectedUsers) while (!hasSelectedUsers)
{ {
@ -2844,7 +2767,7 @@ public class Program
List<string> listUsernames = new(); List<string> listUsernames = new();
foreach (var item in listSelection) foreach (var item in listSelection)
{ {
long listId = lists[item.Replace("[red]", "").Replace("[/]", "")]; int listId = lists[item.Replace("[red]", "").Replace("[/]", "")];
List<string> usernames = await apiHelper.GetListUsers($"/lists/{listId}/users", config); List<string> usernames = await apiHelper.GetListUsers($"/lists/{listId}/users", config);
foreach (string user in usernames) foreach (string user in usernames)
{ {
@ -2884,11 +2807,11 @@ public class Program
} }
break; break;
case "[red]Download Single Post[/]": case "[red]Download Single Post[/]":
return (true, new Dictionary<string, long> { { "SinglePost", 0 } }, currentConfig); return (true, new Dictionary<string, int> { { "SinglePost", 0 } }, currentConfig);
case "[red]Download Single Paid Message[/]": case "[red]Download Single Paid Message[/]":
return (true, new Dictionary<string, long> { { "SingleMessage", 0 } }, currentConfig); return (true, new Dictionary<string, int> { { "SingleMessage", 0 } }, currentConfig);
case "[red]Download Purchased Tab[/]": case "[red]Download Purchased Tab[/]":
return (true, new Dictionary<string, long> { { "PurchasedTab", 0 } }, currentConfig); return (true, new Dictionary<string, int> { { "PurchasedTab", 0 } }, currentConfig);
case "[red]Edit config.conf[/]": case "[red]Edit config.conf[/]":
while (true) while (true)
{ {
@ -2956,9 +2879,7 @@ public class Program
var hoconConfig = new StringBuilder(); var hoconConfig = new StringBuilder();
hoconConfig.AppendLine("# Auth"); hoconConfig.AppendLine("# Auth");
hoconConfig.AppendLine("Auth {"); hoconConfig.AppendLine($"DisableBrowserAuth = {newConfig.DisableBrowserAuth.ToString().ToLower()}");
hoconConfig.AppendLine($" DisableBrowserAuth = \"{newConfig.DisableBrowserAuth.ToString().ToLower()}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# External Tools"); hoconConfig.AppendLine("# External Tools");
hoconConfig.AppendLine("External {"); hoconConfig.AppendLine("External {");
hoconConfig.AppendLine($" FFmpegPath = \"{newConfig.FFmpegPath}\""); hoconConfig.AppendLine($" FFmpegPath = \"{newConfig.FFmpegPath}\"");
@ -3060,7 +2981,7 @@ public class Program
currentConfig = newConfig; currentConfig = newConfig;
if (configChanged) if (configChanged)
{ {
return (true, new Dictionary<string, long> { { "ConfigChanged", 0 } }, currentConfig); return (true, new Dictionary<string, int> { { "ConfigChanged", 0 } }, currentConfig);
} }
break; break;
} }
@ -3118,9 +3039,7 @@ public class Program
var hoconConfig = new StringBuilder(); var hoconConfig = new StringBuilder();
hoconConfig.AppendLine("# Auth"); hoconConfig.AppendLine("# Auth");
hoconConfig.AppendLine("Auth {"); hoconConfig.AppendLine($"DisableBrowserAuth = {newConfig.DisableBrowserAuth.ToString().ToLower()}");
hoconConfig.AppendLine($" DisableBrowserAuth = \"{newConfig.DisableBrowserAuth.ToString().ToLower()}\"");
hoconConfig.AppendLine("}");
hoconConfig.AppendLine("# External Tools"); hoconConfig.AppendLine("# External Tools");
hoconConfig.AppendLine("External {"); hoconConfig.AppendLine("External {");
hoconConfig.AppendLine($" FFmpegPath = \"{newConfig.FFmpegPath}\""); hoconConfig.AppendLine($" FFmpegPath = \"{newConfig.FFmpegPath}\"");
@ -3216,7 +3135,7 @@ public class Program
if (configChanged) if (configChanged)
{ {
return (true, new Dictionary<string, long> { { "ConfigChanged", 0 } }, currentConfig); return (true, new Dictionary<string, int> { { "ConfigChanged", 0 } }, currentConfig);
} }
break; break;
@ -3242,7 +3161,7 @@ public class Program
return (true, selectedUsers, currentConfig); // Return true to indicate selected users return (true, selectedUsers, currentConfig); // Return true to indicate selected users
} }
public static List<string> GetMainMenuOptions(Dictionary<string, long> users, Dictionary<string, long> lists) public static List<string> GetMainMenuOptions(Dictionary<string, int> users, Dictionary<string, int> lists)
{ {
if (lists.Count > 0) if (lists.Count > 0)
{ {

View File

@ -516,23 +516,3 @@ Allowed values: Any positive integer or `-1`
Description: You won't need to set this, but if you see errors about the configured timeout of 100 seconds elapsing then Description: You won't need to set this, but if you see errors about the configured timeout of 100 seconds elapsing then
you could set this to be more than 100. It is recommended that you leave this as the default value. you could set this to be more than 100. It is recommended that you leave this as the default value.
## DisableTextSanitization
Type: `boolean`
Default: `false`
Allowed values: `true`, `false`
Description: When enabled, post/message text is stored as-is without XML stripping.
## DownloadVideoResolution
Type: `string`
Default: `"source"`
Allowed values: `"source"`, `"240"`, `"720"`
Description: This allows you to download videos in alternative resolutions, by default videos are downloaded in source resolution but some people prefer smoother videos at a lower resolution.

View File

@ -20,8 +20,6 @@ information about what it does, its default value, and the allowed values.
- [DownloadDateSelection](/config/all-configuration-options#downloaddateselection) - [DownloadDateSelection](/config/all-configuration-options#downloaddateselection)
- [CustomDate](/config/all-configuration-options#customdate) - [CustomDate](/config/all-configuration-options#customdate)
- [ShowScrapeSize](/config/all-configuration-options#showscrapesize) - [ShowScrapeSize](/config/all-configuration-options#showscrapesize)
- [DisableTextSanitization](/config/all-configuration-options#disabletextsanitization)
- [DownloadVideoResolution](/config/all-configuration-options#downloadvideoresolution)
- Media - Media
- [DownloadAvatarHeaderPhoto](/config/all-configuration-options#downloadavatarheaderphoto) - [DownloadAvatarHeaderPhoto](/config/all-configuration-options#downloadavatarheaderphoto)
- [DownloadPaidPosts](/config/all-configuration-options#downloadpaidposts) - [DownloadPaidPosts](/config/all-configuration-options#downloadpaidposts)