Refactor services

This commit is contained in:
whimsical-c4lic0 2026-02-10 12:01:33 -06:00
parent 70738fd4ae
commit 04004c7084
12 changed files with 709 additions and 704 deletions

View File

@ -2,8 +2,11 @@ namespace OF_DL.Helpers;
public static class Constants public static class Constants
{ {
public const string API_URL = "https://onlyfans.com/api2/v2"; public const string ApiUrl = "https://onlyfans.com/api2/v2";
public const int WIDEVINE_RETRY_DELAY = 10; public const int ApiPageSize = 50;
public const int WIDEVINE_MAX_RETRIES = 3;
public const int WidevineRetryDelay = 10;
public const int WidevineMaxRetries = 3;
} }

View File

@ -6,15 +6,15 @@ namespace OF_DL.Helpers;
public static class VersionHelper public static class VersionHelper
{ {
private const string url = "https://git.ofdl.tools/api/v1/repos/sim0n00ps/OF-DL/releases/latest"; private const string Url = "https://git.ofdl.tools/api/v1/repos/sim0n00ps/OF-DL/releases/latest";
private static readonly HttpClient httpClient = new(); private static readonly HttpClient s_httpClient = new();
public static async Task<string?> GetLatestReleaseTag(CancellationToken cancellationToken = default) public static async Task<string?> GetLatestReleaseTag(CancellationToken cancellationToken = default)
{ {
Log.Debug("Calling GetLatestReleaseTag"); Log.Debug("Calling GetLatestReleaseTag");
try try
{ {
HttpResponseMessage response = await httpClient.GetAsync(url, cancellationToken); HttpResponseMessage response = await s_httpClient.GetAsync(Url, cancellationToken);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
@ -22,21 +22,20 @@ public static class VersionHelper
return null; return null;
} }
string body = await response.Content.ReadAsStringAsync(); string body = await response.Content.ReadAsStringAsync(cancellationToken);
Log.Debug("GetLatestReleaseTag API Response: "); Log.Debug("GetLatestReleaseTag API Response: {Body}", body);
Log.Debug(body);
LatestReleaseApiResponse? versionCheckResponse = LatestReleaseApiResponse? versionCheckResponse =
JsonConvert.DeserializeObject<LatestReleaseApiResponse>(body); JsonConvert.DeserializeObject<LatestReleaseApiResponse>(body);
if (versionCheckResponse == null || versionCheckResponse.TagName == "") if (versionCheckResponse != null && versionCheckResponse.TagName != "")
{ {
Log.Debug("GetLatestReleaseTag did not return a valid tag name"); return versionCheckResponse.TagName;
return null;
} }
return versionCheckResponse.TagName; Log.Debug("GetLatestReleaseTag did not return a valid tag name");
return null;
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {

View File

@ -74,7 +74,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
else else
{ {
//Get rules from GitHub and fallback to local file // Get rules from GitHub and fallback to a local file
string? dynamicRulesJson = GetDynamicRules(); string? dynamicRulesJson = GetDynamicRules();
if (!string.IsNullOrEmpty(dynamicRulesJson)) if (!string.IsNullOrEmpty(dynamicRulesJson))
{ {
@ -90,7 +90,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
Log.Debug("Using dynamic rules from local file"); Log.Debug("Using dynamic rules from local file");
root = JsonConvert.DeserializeObject<DynamicRules>(File.ReadAllText("rules.json")); root = JsonConvert.DeserializeObject<DynamicRules>(File.ReadAllText("rules.json"));
// Cache the dynamic rules from local file to prevent unnecessary disk // Cache the dynamic rules from a local file to prevent unnecessary disk
// operations and frequent call to GitHub. Since the GitHub dynamic rules // operations and frequent call to GitHub. Since the GitHub dynamic rules
// are preferred to the local file, the cache time is shorter than when dynamic rules // are preferred to the local file, the cache time is shorter than when dynamic rules
// are successfully retrieved from GitHub. // are successfully retrieved from GitHub.
@ -160,10 +160,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
UserEntities.User user = new(); UserEntities.User user = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "order", "publish_date_asc" } { "limit", Constants.ApiPageSize.ToString() }, { "order", "publish_date_asc" }
}; };
HttpClient client = new(); HttpClient client = new();
@ -386,20 +385,17 @@ public class ApiService(IAuthService authService, IConfigService configService,
/// <param name="endpoint">The endpoint to query.</param> /// <param name="endpoint">The endpoint to query.</param>
/// <param name="username">Optional username context.</param> /// <param name="username">Optional username context.</param>
/// <param name="folder">The creator folder path.</param> /// <param name="folder">The creator folder path.</param>
/// <param name="paidPostIds">Paid post media IDs.</param>
/// <returns>A mediaId-to-URL map.</returns> /// <returns>A mediaId-to-URL map.</returns>
public async Task<Dictionary<long, string>?> GetMedia(MediaType mediatype, public async Task<Dictionary<long, string>?> GetMedia(MediaType mediatype,
string endpoint, string endpoint,
string? username, string? username,
string folder, string folder)
List<long> paidPostIds)
{ {
Log.Debug($"Calling GetMedia - {username}"); Log.Debug($"Calling GetMedia - {username}");
try try
{ {
Dictionary<long, string> returnUrls = new(); Dictionary<long, string> returnUrls = new();
const int postLimit = 50;
const int limit = 5; const int limit = 5;
int offset = 0; int offset = 0;
@ -410,7 +406,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
case MediaType.Stories: case MediaType.Stories:
getParams = new Dictionary<string, string> getParams = new Dictionary<string, string>
{ {
{ "limit", postLimit.ToString() }, { "order", "publish_date_desc" }, { "skip_users", "all" } { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" },
{ "skip_users", "all" }
}; };
break; break;
@ -478,9 +476,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
continue; continue;
} }
if (medium.CanView && !returnUrls.ContainsKey(medium.Id)) if (medium.CanView)
{ {
returnUrls.Add(medium.Id, mediaUrl); returnUrls.TryAdd(medium.Id, mediaUrl);
} }
} }
} }
@ -555,7 +553,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
foreach (HighlightEntities.Story item in highlightMedia.Stories) foreach (HighlightEntities.Story item in highlightMedia.Stories)
{ {
DateTime? createdAt = item.Media != null && item.Media.Count > 0 DateTime? createdAt = item.Media is { Count: > 0 }
? item.Media[0].CreatedAt ? item.Media[0].CreatedAt
: null; : null;
@ -572,8 +570,11 @@ public class ApiService(IAuthService authService, IConfigService configService,
await dbService.AddStory(folder, item.Id, "", "0", false, false, DateTime.Now); await dbService.AddStory(folder, item.Id, "", "0", false, false, DateTime.Now);
} }
if (item.Media != null && item.Media.Count > 0 && item.Media[0].CanView) if (item.Media is not { Count: > 0 } || !item.Media[0].CanView)
{ {
continue;
}
string? storyUrl = item.Media[0].Files?.Full?.Url; string? storyUrl = item.Media[0].Files?.Full?.Url;
string storyUrlValue = storyUrl ?? string.Empty; string storyUrlValue = storyUrl ?? string.Empty;
foreach (HighlightEntities.Medium medium in item.Media) foreach (HighlightEntities.Medium medium in item.Media)
@ -594,7 +595,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return returnUrls; return returnUrls;
} }
@ -625,10 +625,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
PurchasedEntities.PaidPostCollection paidPostCollection = new(); PurchasedEntities.PaidPostCollection paidPostCollection = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "skip_users", "all" }, { "skip_users", "all" },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "format", "infinite" }, { "format", "infinite" },
@ -657,25 +656,29 @@ public class ApiService(IAuthService authService, IConfigService configService,
break; break;
} }
getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + postLimit); getParams["offset"] =
Convert.ToString(Convert.ToInt32(getParams["offset"]) + Constants.ApiPageSize);
} }
} }
List<PurchasedEntities.ListItem> paidPostList = paidPosts.List; List<PurchasedEntities.ListItem> paidPostList = paidPosts.List;
foreach (PurchasedEntities.ListItem purchase in paidPostList) foreach (PurchasedEntities.ListItem purchase in paidPostList)
{ {
if (purchase.ResponseType == "post" && purchase.Media != null && purchase.Media.Count > 0) if (purchase.ResponseType != "post" || purchase.Media is not { Count: > 0 })
{ {
List<long> previewids = new(); continue;
}
List<long> previewIds = [];
if (purchase.Previews != null) if (purchase.Previews != null)
{ {
for (int i = 0; i < purchase.Previews.Count; i++) for (int i = 0; i < purchase.Previews.Count; i++)
{ {
if (purchase.Previews[i] is long previewId) if (purchase.Previews[i] is long previewId)
{ {
if (!previewids.Contains(previewId)) if (!previewIds.Contains(previewId))
{ {
previewids.Add(previewId); previewIds.Add(previewId);
} }
} }
} }
@ -686,9 +689,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
{ {
if (purchase.Preview[i] is long previewId) if (purchase.Preview[i] is long previewId)
{ {
if (!previewids.Contains(previewId)) if (!previewIds.Contains(previewId))
{ {
previewids.Add(previewId); previewIds.Add(previewId);
} }
} }
} }
@ -698,11 +701,11 @@ public class ApiService(IAuthService authService, IConfigService configService,
bool isArchived = purchase.IsArchived ?? false; bool isArchived = purchase.IsArchived ?? false;
await dbService.AddPost(folder, purchase.Id, purchase.Text ?? "", await dbService.AddPost(folder, purchase.Id, purchase.Text ?? "",
purchase.Price ?? "0", purchase.Price ?? "0",
purchase.Price != null && purchase.IsOpened, isArchived, createdAt); purchase is { Price: not null, IsOpened: true }, isArchived, createdAt);
paidPostCollection.PaidPostObjects.Add(purchase); paidPostCollection.PaidPostObjects.Add(purchase);
foreach (MessageEntities.Medium medium in purchase.Media) foreach (MessageEntities.Medium medium in purchase.Media)
{ {
if (!previewids.Contains(medium.Id)) if (!previewIds.Contains(medium.Id))
{ {
paidPostIds.Add(medium.Id); paidPostIds.Add(medium.Id);
} }
@ -714,11 +717,11 @@ public class ApiService(IAuthService authService, IConfigService configService,
string mediaType = ResolveMediaType(medium.Type) ?? ""; string mediaType = ResolveMediaType(medium.Type) ?? "";
string? fullUrl = medium.Files?.Full?.Url; string? fullUrl = medium.Files?.Full?.Url;
bool isPreview = previewids.Contains(medium.Id); bool isPreview = previewIds.Contains(medium.Id);
if (previewids.Count > 0) if (previewIds.Count > 0)
{ {
bool has = previewids.Any(cus => cus.Equals(medium.Id)); bool has = previewIds.Any(cus => cus.Equals(medium.Id));
if (!has && medium.CanView && !string.IsNullOrEmpty(fullUrl)) if (!has && medium.CanView && !string.IsNullOrEmpty(fullUrl))
{ {
if (!paidPostCollection.PaidPosts.ContainsKey(medium.Id)) if (!paidPostCollection.PaidPosts.ContainsKey(medium.Id))
@ -775,7 +778,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return paidPostCollection; return paidPostCollection;
} }
@ -804,10 +806,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
PostEntities.PostCollection postCollection = new(); PostEntities.PostCollection postCollection = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "format", "infinite" }, { "format", "infinite" },
{ "skip_users", "all" } { "skip_users", "all" }
@ -816,8 +817,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
DownloadDateSelection downloadDateSelection = DownloadDateSelection.before; DownloadDateSelection downloadDateSelection = DownloadDateSelection.before;
DateTime? downloadAsOf = null; DateTime? downloadAsOf = null;
if (configService.CurrentConfig.DownloadOnlySpecificDates && if (configService.CurrentConfig is { DownloadOnlySpecificDates: true, CustomDate: not null })
configService.CurrentConfig.CustomDate.HasValue)
{ {
downloadDateSelection = configService.CurrentConfig.DownloadDateSelection; downloadDateSelection = configService.CurrentConfig.DownloadDateSelection;
downloadAsOf = configService.CurrentConfig.CustomDate; downloadAsOf = configService.CurrentConfig.CustomDate;
@ -890,27 +890,34 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
List<long> postPreviewIds = new(); List<long> postPreviewIds = [];
if (post.Preview != null && post.Preview.Count > 0) if (post.Preview is { Count: > 0 })
{ {
for (int i = 0; i < post.Preview.Count; i++) for (int i = 0; i < post.Preview.Count; i++)
{ {
if (post.Preview[i] is long previewId) if (post.Preview[i] is not long previewId)
{ {
continue;
}
if (!postPreviewIds.Contains(previewId)) if (!postPreviewIds.Contains(previewId))
{ {
postPreviewIds.Add(previewId); postPreviewIds.Add(previewId);
} }
} }
} }
}
await dbService.AddPost(folder, post.Id, !string.IsNullOrEmpty(post.RawText) ? post.RawText : "", await dbService.AddPost(folder, post.Id, !string.IsNullOrEmpty(post.RawText) ? post.RawText : "",
post.Price ?? "0", post.Price != null && post.IsOpened, post.Price ?? "0", post is { Price: not null, IsOpened: true },
post.IsArchived, post.PostedAt); post.IsArchived, post.PostedAt);
postCollection.PostObjects.Add(post); postCollection.PostObjects.Add(post);
if (post.Media != null && post.Media.Count > 0)
if (post.Media is not { Count: > 0 })
{ {
continue;
}
foreach (PostEntities.Medium medium in post.Media) foreach (PostEntities.Medium medium in post.Media)
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -963,7 +970,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return postCollection; return postCollection;
} }
@ -997,29 +1003,35 @@ public class ApiService(IAuthService authService, IConfigService configService,
if (singlePostDto != null) if (singlePostDto != null)
{ {
List<long> postPreviewIds = new(); List<long> postPreviewIds = [];
if (singlePost.Preview != null && singlePost.Preview.Count > 0) if (singlePost.Preview is { Count: > 0 })
{ {
for (int i = 0; i < singlePost.Preview.Count; i++) for (int i = 0; i < singlePost.Preview.Count; i++)
{ {
if (singlePost.Preview[i] is long previewId) if (singlePost.Preview[i] is not long previewId)
{ {
continue;
}
if (!postPreviewIds.Contains(previewId)) if (!postPreviewIds.Contains(previewId))
{ {
postPreviewIds.Add(previewId); postPreviewIds.Add(previewId);
} }
} }
} }
}
await dbService.AddPost(folder, singlePost.Id, await dbService.AddPost(folder, singlePost.Id,
!string.IsNullOrEmpty(singlePost.Text) ? singlePost.Text : "", !string.IsNullOrEmpty(singlePost.Text) ? singlePost.Text : "",
singlePost.Price ?? "0", singlePost.Price ?? "0",
singlePost.Price != null && singlePost.IsOpened, singlePost.IsArchived, singlePost is { Price: not null, IsOpened: true }, singlePost.IsArchived,
singlePost.PostedAt); singlePost.PostedAt);
singlePostCollection.SinglePostObjects.Add(singlePost); singlePostCollection.SinglePostObjects.Add(singlePost);
if (singlePost.Media != null && singlePost.Media.Count > 0)
if (singlePost.Media == null || singlePost.Media.Count <= 0)
{ {
return singlePostCollection;
}
foreach (PostEntities.Medium medium in singlePost.Media) foreach (PostEntities.Medium medium in singlePost.Media)
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -1104,7 +1116,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return singlePostCollection; return singlePostCollection;
} }
@ -1133,18 +1144,16 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
StreamEntities.StreamsCollection streamsCollection = new(); StreamEntities.StreamsCollection streamsCollection = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "format", "infinite" }, { "format", "infinite" },
{ "skip_users", "all" } { "skip_users", "all" }
}; };
DownloadDateSelection downloadDateSelection = DownloadDateSelection.before; DownloadDateSelection downloadDateSelection = DownloadDateSelection.before;
if (configService.CurrentConfig.DownloadOnlySpecificDates && if (configService.CurrentConfig is { DownloadOnlySpecificDates: true, CustomDate: not null })
configService.CurrentConfig.CustomDate.HasValue)
{ {
downloadDateSelection = configService.CurrentConfig.DownloadDateSelection; downloadDateSelection = configService.CurrentConfig.DownloadDateSelection;
} }
@ -1190,27 +1199,34 @@ public class ApiService(IAuthService authService, IConfigService configService,
List<StreamEntities.ListItem> streamList = streams.List; List<StreamEntities.ListItem> streamList = streams.List;
foreach (StreamEntities.ListItem stream in streamList) foreach (StreamEntities.ListItem stream in streamList)
{ {
List<long> streamPreviewIds = new(); List<long> streamPreviewIds = [];
if (stream.Preview != null && stream.Preview.Count > 0) if (stream.Preview is { Count: > 0 })
{ {
for (int i = 0; i < stream.Preview.Count; i++) for (int i = 0; i < stream.Preview.Count; i++)
{ {
if (stream.Preview[i] is long previewId) if (stream.Preview[i] is not long previewId)
{ {
continue;
}
if (!streamPreviewIds.Contains(previewId)) if (!streamPreviewIds.Contains(previewId))
{ {
streamPreviewIds.Add(previewId); streamPreviewIds.Add(previewId);
} }
} }
} }
}
await dbService.AddPost(folder, stream.Id, !string.IsNullOrEmpty(stream.Text) ? stream.Text : "", await dbService.AddPost(folder, stream.Id, !string.IsNullOrEmpty(stream.Text) ? stream.Text : "",
stream.Price ?? "0", stream.Price != null && stream.IsOpened, stream.Price ?? "0", stream is { Price: not null, IsOpened: true },
stream.IsArchived, stream.PostedAt); stream.IsArchived, stream.PostedAt);
streamsCollection.StreamObjects.Add(stream); streamsCollection.StreamObjects.Add(stream);
if (stream.Media != null && stream.Media.Count > 0)
if (stream.Media is not { Count: > 0 })
{ {
continue;
}
foreach (StreamEntities.Medium medium in stream.Media) foreach (StreamEntities.Medium medium in stream.Media)
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -1252,7 +1268,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return streamsCollection; return streamsCollection;
} }
@ -1280,10 +1295,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
ArchivedEntities.ArchivedCollection archivedCollection = new(); ArchivedEntities.ArchivedCollection archivedCollection = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "skip_users", "all" }, { "skip_users", "all" },
{ "format", "infinite" }, { "format", "infinite" },
@ -1292,8 +1306,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
}; };
DownloadDateSelection downloadDateSelection = DownloadDateSelection.before; DownloadDateSelection downloadDateSelection = DownloadDateSelection.before;
if (configService.CurrentConfig.DownloadOnlySpecificDates && if (configService.CurrentConfig is { DownloadOnlySpecificDates: true, CustomDate: not null })
configService.CurrentConfig.CustomDate.HasValue)
{ {
downloadDateSelection = configService.CurrentConfig.DownloadDateSelection; downloadDateSelection = configService.CurrentConfig.DownloadDateSelection;
} }
@ -1364,10 +1377,15 @@ public class ApiService(IAuthService authService, IConfigService configService,
await dbService.AddPost(folder, archive.Id, archive.Text ?? "", await dbService.AddPost(folder, archive.Id, archive.Text ?? "",
archive.Price ?? "0", archive.Price ?? "0",
archive.Price != null && archive.IsOpened, archive.IsArchived, archive.PostedAt); archive is { Price: not null, IsOpened: true }, archive.IsArchived, archive.PostedAt);
archivedCollection.ArchivedPostObjects.Add(archive); archivedCollection.ArchivedPostObjects.Add(archive);
if (archive.Media != null && archive.Media.Count > 0)
if (archive.Media is not { Count: > 0 })
{ {
continue;
}
foreach (ArchivedEntities.Medium medium in archive.Media) foreach (ArchivedEntities.Medium medium in archive.Media)
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -1404,7 +1422,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return archivedCollection; return archivedCollection;
} }
@ -1432,10 +1449,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
MessageEntities.MessageCollection messageCollection = new(); MessageEntities.MessageCollection messageCollection = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "order", "desc" }, { "skip_users", "all" } { "limit", Constants.ApiPageSize.ToString() }, { "order", "desc" }, { "skip_users", "all" }
}; };
int currentUserId = GetCurrentUserIdOrDefault(); int currentUserId = GetCurrentUserIdOrDefault();
@ -1476,33 +1492,41 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
List<long> messagePreviewIds = new(); List<long> messagePreviewIds = [];
if (list.Previews != null && list.Previews.Count > 0)
if (list.Previews is { Count: > 0 })
{ {
for (int i = 0; i < list.Previews.Count; i++) for (int i = 0; i < list.Previews.Count; i++)
{ {
if (list.Previews[i] is long previewId) if (list.Previews[i] is not long previewId)
{ {
continue;
}
if (!messagePreviewIds.Contains(previewId)) if (!messagePreviewIds.Contains(previewId))
{ {
messagePreviewIds.Add(previewId); messagePreviewIds.Add(previewId);
} }
} }
} }
if (configService.CurrentConfig.IgnoreOwnMessages && list.FromUser?.Id == currentUserId)
{
continue;
} }
if (!configService.CurrentConfig.IgnoreOwnMessages || list.FromUser?.Id != currentUserId)
{
DateTime createdAt = list.CreatedAt ?? DateTime.Now; DateTime createdAt = list.CreatedAt ?? DateTime.Now;
await dbService.AddMessage(folder, list.Id, list.Text ?? "", list.Price ?? "0", await dbService.AddMessage(folder, list.Id, list.Text ?? "", list.Price ?? "0",
list.CanPurchaseReason == "opened" || list.CanPurchaseReason == "opened" ||
(list.CanPurchaseReason == "opened" && ((bool?)null ?? false)), false, (list.CanPurchaseReason == "opened" && ((bool?)null ?? false)), false,
createdAt, createdAt,
list.FromUser?.Id ?? int.MinValue); list.FromUser?.Id ?? int.MinValue);
messageCollection.MessageObjects.Add(list); messageCollection.MessageObjects.Add(list);
if (list.CanPurchaseReason != "opened" && list.Media != null && list.Media.Count > 0)
if (list.CanPurchaseReason != "opened" && list.Media is { Count: > 0 })
{ {
foreach (MessageEntities.Medium medium in list.Media ?? new List<MessageEntities.Medium>()) foreach (MessageEntities.Medium medium in list.Media ?? [])
{ {
string mediaType = ResolveMediaType(medium.Type) ?? string.Empty; string mediaType = ResolveMediaType(medium.Type) ?? string.Empty;
string? fullUrl = medium.Files?.Full?.Url; string? fullUrl = medium.Files?.Full?.Url;
@ -1589,7 +1613,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
return messageCollection; return messageCollection;
} }
@ -1614,8 +1637,8 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
PurchasedEntities.SinglePaidMessageCollection singlePaidMessageCollection = new(); PurchasedEntities.SinglePaidMessageCollection singlePaidMessageCollection = new();
const int postLimit = 50; Dictionary<string, string> getParams =
Dictionary<string, string> getParams = new() { { "limit", postLimit.ToString() }, { "order", "desc" } }; new() { { "limit", Constants.ApiPageSize.ToString() }, { "order", "desc" } };
int currentUserId = GetCurrentUserIdOrDefault(); int currentUserId = GetCurrentUserIdOrDefault();
string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient()); string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient());
@ -1623,31 +1646,41 @@ public class ApiService(IAuthService authService, IConfigService configService,
DeserializeJson<MessageDtos.SingleMessageDto>(body, s_mJsonSerializerSettings); DeserializeJson<MessageDtos.SingleMessageDto>(body, s_mJsonSerializerSettings);
MessageEntities.SingleMessage message = MessagesMapper.FromDto(messageDto); MessageEntities.SingleMessage message = MessagesMapper.FromDto(messageDto);
if (!configService.CurrentConfig.IgnoreOwnMessages || message.FromUser?.Id != currentUserId) if (configService.CurrentConfig.IgnoreOwnMessages && message.FromUser?.Id == currentUserId)
{ {
return singlePaidMessageCollection;
}
DateTime createdAt = message.CreatedAt ?? DateTime.Now; DateTime createdAt = message.CreatedAt ?? DateTime.Now;
await dbService.AddMessage(folder, message.Id, message.Text ?? "", await dbService.AddMessage(folder, message.Id, message.Text ?? "",
message.Price?.ToString() ?? "0", true, false, message.Price?.ToString() ?? "0", true, false,
createdAt, createdAt,
message.FromUser?.Id ?? int.MinValue); message.FromUser?.Id ?? int.MinValue);
singlePaidMessageCollection.SingleMessageObjects.Add(message); singlePaidMessageCollection.SingleMessageObjects.Add(message);
List<long> messagePreviewIds = new();
if (message.Previews != null && message.Previews.Count > 0) List<long> messagePreviewIds = [];
if (message.Previews is { Count: > 0 })
{ {
for (int i = 0; i < message.Previews.Count; i++) for (int i = 0; i < message.Previews.Count; i++)
{ {
if (message.Previews[i] is long previewId) if (message.Previews[i] is not long previewId)
{ {
continue;
}
if (!messagePreviewIds.Contains(previewId)) if (!messagePreviewIds.Contains(previewId))
{ {
messagePreviewIds.Add(previewId); messagePreviewIds.Add(previewId);
} }
} }
} }
if (message.Media is not { Count: > 0 })
{
return singlePaidMessageCollection;
} }
if (message.Media != null && message.Media.Count > 0)
{
foreach (MessageEntities.Medium medium in message.Media) foreach (MessageEntities.Medium medium in message.Media)
{ {
string mediaType = ResolveMediaType(medium.Type) ?? string.Empty; string mediaType = ResolveMediaType(medium.Type) ?? string.Empty;
@ -1661,14 +1694,15 @@ public class ApiService(IAuthService authService, IConfigService configService,
continue; continue;
} }
if (!singlePaidMessageCollection.SingleMessages.ContainsKey(medium.Id)) if (!singlePaidMessageCollection.SingleMessages.TryAdd(medium.Id, fullUrl))
{ {
continue;
}
await dbService.AddMedia(folder, medium.Id, message.Id, fullUrl, null, null, null, await dbService.AddMedia(folder, medium.Id, message.Id, fullUrl, null, null, null,
"Messages", mediaType, isPreview, false, null); "Messages", mediaType, isPreview, false, null);
singlePaidMessageCollection.SingleMessages.Add(medium.Id, fullUrl);
singlePaidMessageCollection.SingleMessageMedia.Add(medium); singlePaidMessageCollection.SingleMessageMedia.Add(medium);
} }
}
else if (isPreview && medium.CanView && !string.IsNullOrEmpty(fullUrl)) else if (isPreview && medium.CanView && !string.IsNullOrEmpty(fullUrl))
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -1722,8 +1756,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
}
return singlePaidMessageCollection; return singlePaidMessageCollection;
} }
@ -1753,10 +1785,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
PurchasedEntities.PaidMessageCollection paidMessageCollection = new(); PurchasedEntities.PaidMessageCollection paidMessageCollection = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "format", "infinite" }, { "format", "infinite" },
{ "author", username }, { "author", username },
@ -1780,7 +1811,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
HttpClient loopclient = GetHttpClient(); HttpClient loopclient = GetHttpClient();
HttpRequestMessage looprequest = HttpRequestMessage looprequest =
new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{loopqueryParams}"); new(HttpMethod.Get, $"{Constants.ApiUrl}{endpoint}{loopqueryParams}");
foreach (KeyValuePair<string, string> keyValuePair in loopheaders) foreach (KeyValuePair<string, string> keyValuePair in loopheaders)
{ {
@ -1803,7 +1834,8 @@ public class ApiService(IAuthService authService, IConfigService configService,
break; break;
} }
getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + postLimit); getParams["offset"] =
Convert.ToString(Convert.ToInt32(getParams["offset"]) + Constants.ApiPageSize);
} }
} }
@ -1816,8 +1848,11 @@ public class ApiService(IAuthService authService, IConfigService configService,
.OrderByDescending(p => p.PostedAt ?? p.CreatedAt)) .OrderByDescending(p => p.PostedAt ?? p.CreatedAt))
{ {
long fromUserId = purchase.FromUser?.Id ?? long.MinValue; long fromUserId = purchase.FromUser?.Id ?? long.MinValue;
if (!configService.CurrentConfig.IgnoreOwnMessages || fromUserId != currentUserId) if (configService.CurrentConfig.IgnoreOwnMessages && fromUserId == currentUserId)
{ {
continue;
}
DateTime createdAt = purchase.PostedAt ?? purchase.CreatedAt ?? DateTime.Now; DateTime createdAt = purchase.PostedAt ?? purchase.CreatedAt ?? DateTime.Now;
await dbService.AddMessage(folder, purchase.Id, await dbService.AddMessage(folder, purchase.Id,
purchase.Text ?? "", purchase.Text ?? "",
@ -1825,19 +1860,24 @@ public class ApiService(IAuthService authService, IConfigService configService,
fromUserId); fromUserId);
paidMessageCollection.PaidMessageObjects.Add(purchase); paidMessageCollection.PaidMessageObjects.Add(purchase);
if (purchase.Media != null && purchase.Media.Count > 0) if (purchase.Media is not { Count: > 0 })
{ {
List<long> previewids = new(); continue;
}
List<long> previewIds = [];
if (purchase.Previews != null) if (purchase.Previews != null)
{ {
for (int i = 0; i < purchase.Previews.Count; i++) for (int i = 0; i < purchase.Previews.Count; i++)
{ {
if (purchase.Previews[i] is long previewId) if (purchase.Previews[i] is not long previewId)
{ {
if (!previewids.Contains(previewId)) continue;
{
previewids.Add(previewId);
} }
if (!previewIds.Contains(previewId))
{
previewIds.Add(previewId);
} }
} }
} }
@ -1847,9 +1887,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
{ {
if (purchase.Preview[i] is long previewId) if (purchase.Preview[i] is long previewId)
{ {
if (!previewids.Contains(previewId)) if (!previewIds.Contains(previewId))
{ {
previewids.Add(previewId); previewIds.Add(previewId);
} }
} }
} }
@ -1859,11 +1899,11 @@ public class ApiService(IAuthService authService, IConfigService configService,
{ {
string mediaType = ResolveMediaType(medium.Type) ?? string.Empty; string mediaType = ResolveMediaType(medium.Type) ?? string.Empty;
string? fullUrl = medium.Files?.Full?.Url; string? fullUrl = medium.Files?.Full?.Url;
bool isPreview = previewids.Contains(medium.Id); bool isPreview = previewIds.Contains(medium.Id);
if (previewids.Count > 0) if (previewIds.Count > 0)
{ {
bool has = previewids.Any(cus => cus.Equals(medium.Id)); bool has = previewIds.Any(cus => cus.Equals(medium.Id));
if (!has && medium.CanView && !string.IsNullOrEmpty(fullUrl)) if (!has && medium.CanView && !string.IsNullOrEmpty(fullUrl))
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -1943,8 +1983,6 @@ public class ApiService(IAuthService authService, IConfigService configService,
} }
} }
} }
}
}
return paidMessageCollection; return paidMessageCollection;
} }
@ -1969,10 +2007,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
try try
{ {
Dictionary<string, long> purchasedTabUsers = new(); Dictionary<string, long> purchasedTabUsers = new();
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "format", "infinite" }, { "format", "infinite" },
{ "skip_users", "all" } { "skip_users", "all" }
@ -1998,7 +2035,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
HttpClient loopclient = GetHttpClient(); HttpClient loopclient = GetHttpClient();
HttpRequestMessage looprequest = HttpRequestMessage looprequest =
new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{loopqueryParams}"); new(HttpMethod.Get, $"{Constants.ApiUrl}{endpoint}{loopqueryParams}");
foreach (KeyValuePair<string, string> keyValuePair in loopheaders) foreach (KeyValuePair<string, string> keyValuePair in loopheaders)
{ {
@ -2020,7 +2057,8 @@ public class ApiService(IAuthService authService, IConfigService configService,
break; break;
} }
getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + postLimit); getParams["offset"] =
Convert.ToString(Convert.ToInt32(getParams["offset"]) + Constants.ApiPageSize);
} }
} }
@ -2039,10 +2077,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
string? matchedUsername = users.FirstOrDefault(x => x.Value == fromUserId).Key; string? matchedUsername = users.FirstOrDefault(x => x.Value == fromUserId).Key;
if (!string.IsNullOrEmpty(matchedUsername)) if (!string.IsNullOrEmpty(matchedUsername))
{ {
if (!purchasedTabUsers.ContainsKey(matchedUsername)) purchasedTabUsers.TryAdd(matchedUsername, fromUserId);
{
purchasedTabUsers.Add(matchedUsername, fromUserId);
}
} }
else if (!purchasedTabUsers.ContainsKey($"Deleted User - {fromUserId}")) else if (!purchasedTabUsers.ContainsKey($"Deleted User - {fromUserId}"))
{ {
@ -2064,9 +2099,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
Log.Debug("Content creator not longer exists - {0}", fromUserId); Log.Debug("Content creator not longer exists - {0}", fromUserId);
} }
else if (!purchasedTabUsers.ContainsKey(fetchedUsername)) else
{ {
purchasedTabUsers.Add(fetchedUsername, fromUserId); purchasedTabUsers.TryAdd(fetchedUsername, fromUserId);
} }
} }
} }
@ -2139,10 +2174,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
{ {
Dictionary<long, List<PurchasedEntities.ListItem>> userPurchases = new(); Dictionary<long, List<PurchasedEntities.ListItem>> userPurchases = new();
List<PurchasedEntities.PurchasedTabCollection> purchasedTabCollections = []; List<PurchasedEntities.PurchasedTabCollection> purchasedTabCollections = [];
const int postLimit = 50;
Dictionary<string, string> getParams = new() Dictionary<string, string> getParams = new()
{ {
{ "limit", postLimit.ToString() }, { "limit", Constants.ApiPageSize.ToString() },
{ "order", "publish_date_desc" }, { "order", "publish_date_desc" },
{ "format", "infinite" }, { "format", "infinite" },
{ "skip_users", "all" } { "skip_users", "all" }
@ -2163,7 +2197,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
HttpClient loopclient = GetHttpClient(); HttpClient loopclient = GetHttpClient();
HttpRequestMessage looprequest = HttpRequestMessage looprequest =
new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{loopqueryParams}"); new(HttpMethod.Get, $"{Constants.ApiUrl}{endpoint}{loopqueryParams}");
foreach (KeyValuePair<string, string> keyValuePair in loopheaders) foreach (KeyValuePair<string, string> keyValuePair in loopheaders)
{ {
@ -2185,7 +2219,8 @@ public class ApiService(IAuthService authService, IConfigService configService,
break; break;
} }
getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + postLimit); getParams["offset"] =
Convert.ToString(Convert.ToInt32(getParams["offset"]) + Constants.ApiPageSize);
} }
} }
@ -2274,10 +2309,12 @@ public class ApiService(IAuthService authService, IConfigService configService,
await dbService.AddPost(path, purchase.Id, await dbService.AddPost(path, purchase.Id,
purchase.Text ?? "", purchase.Text ?? "",
purchase.Price ?? "0", purchase.Price ?? "0",
purchase.Price != null && purchase.IsOpened, purchase is { Price: not null, IsOpened: true },
isArchived, isArchived,
createdAt); createdAt);
purchasedTabCollection.PaidPosts.PaidPostObjects.Add(purchase); purchasedTabCollection.PaidPosts.PaidPostObjects.Add(purchase);
foreach (MessageEntities.Medium medium in purchase.Media) foreach (MessageEntities.Medium medium in purchase.Media)
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -2356,18 +2393,18 @@ public class ApiService(IAuthService authService, IConfigService configService,
messageCreatedAt, fromUserId); messageCreatedAt, fromUserId);
purchasedTabCollection.PaidMessages.PaidMessageObjects.Add(purchase); purchasedTabCollection.PaidMessages.PaidMessageObjects.Add(purchase);
if (purchase.Media != null && purchase.Media.Count > 0) if (purchase.Media is { Count: > 0 })
{ {
List<long> paidMessagePreviewids = new(); List<long> paidMessagePreviewIds = [];
if (purchase.Previews != null) if (purchase.Previews != null)
{ {
for (int i = 0; i < purchase.Previews.Count; i++) for (int i = 0; i < purchase.Previews.Count; i++)
{ {
if (purchase.Previews[i] is long previewId) if (purchase.Previews[i] is long previewId)
{ {
if (!paidMessagePreviewids.Contains(previewId)) if (!paidMessagePreviewIds.Contains(previewId))
{ {
paidMessagePreviewids.Add(previewId); paidMessagePreviewIds.Add(previewId);
} }
} }
} }
@ -2378,9 +2415,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
{ {
if (purchase.Preview[i] is long previewId) if (purchase.Preview[i] is long previewId)
{ {
if (!paidMessagePreviewids.Contains(previewId)) if (!paidMessagePreviewIds.Contains(previewId))
{ {
paidMessagePreviewids.Add(previewId); paidMessagePreviewIds.Add(previewId);
} }
} }
} }
@ -2388,12 +2425,12 @@ public class ApiService(IAuthService authService, IConfigService configService,
foreach (MessageEntities.Medium medium in purchase.Media) foreach (MessageEntities.Medium medium in purchase.Media)
{ {
if (paidMessagePreviewids.Count > 0) if (paidMessagePreviewIds.Count > 0)
{ {
string mediaType = ResolveMediaType(medium.Type) ?? string.Empty; string mediaType = ResolveMediaType(medium.Type) ?? string.Empty;
string? fullUrl = medium.Files?.Full?.Url; string? fullUrl = medium.Files?.Full?.Url;
bool isPreview = paidMessagePreviewids.Contains(medium.Id); bool isPreview = paidMessagePreviewIds.Contains(medium.Id);
bool has = paidMessagePreviewids.Any(cus => cus.Equals(medium.Id)); bool has = paidMessagePreviewIds.Any(cus => cus.Equals(medium.Id));
if (!has && medium.CanView && !string.IsNullOrEmpty(fullUrl)) if (!has && medium.CanView && !string.IsNullOrEmpty(fullUrl))
{ {
if (!IsMediaTypeDownloadEnabled(medium.Type)) if (!IsMediaTypeDownloadEnabled(medium.Type))
@ -2440,7 +2477,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
{ {
string mediaType = ResolveMediaType(medium.Type) ?? string.Empty; string mediaType = ResolveMediaType(medium.Type) ?? string.Empty;
string? fullUrl = medium.Files?.Full?.Url; string? fullUrl = medium.Files?.Full?.Url;
bool isPreview = paidMessagePreviewids.Contains(medium.Id); bool isPreview = paidMessagePreviewIds.Contains(medium.Id);
if (medium.CanView && !string.IsNullOrEmpty(fullUrl)) if (medium.CanView && !string.IsNullOrEmpty(fullUrl))
{ {
@ -2729,9 +2766,9 @@ public class ApiService(IAuthService authService, IConfigService configService,
Dictionary<string, string> headers = GetDynamicHeaders($"/api2/v2{endpoint}", queryParams); Dictionary<string, string> headers = GetDynamicHeaders($"/api2/v2{endpoint}", queryParams);
HttpRequestMessage request = new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{queryParams}"); HttpRequestMessage request = new(HttpMethod.Get, $"{Constants.ApiUrl}{endpoint}{queryParams}");
Log.Debug($"Full request URL: {Constants.API_URL}{endpoint}{queryParams}"); Log.Debug($"Full request URL: {Constants.ApiUrl}{endpoint}{queryParams}");
foreach (KeyValuePair<string, string> keyValuePair in headers) foreach (KeyValuePair<string, string> keyValuePair in headers)
{ {
@ -2756,7 +2793,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
private HttpClient GetHttpClient() private HttpClient GetHttpClient()
{ {
HttpClient client = new(); HttpClient client = new();
if (configService.CurrentConfig.Timeout != null && configService.CurrentConfig.Timeout > 0) if (configService.CurrentConfig.Timeout is > 0)
{ {
client.Timeout = TimeSpan.FromSeconds(configService.CurrentConfig.Timeout.Value); client.Timeout = TimeSpan.FromSeconds(configService.CurrentConfig.Timeout.Value);
} }

View File

@ -572,12 +572,14 @@ public class DbService(IConfigService configService) : IDbService
while (await reader.ReadAsync()) while (await reader.ReadAsync())
{ {
if (reader["name"].ToString() == "record_created_at") if (reader["name"].ToString() != "record_created_at")
{ {
continue;
}
columnExists = true; columnExists = true;
break; break;
} }
}
if (!columnExists) if (!columnExists)
{ {

View File

@ -18,10 +18,10 @@ public class DownloadOrchestrationService(
/// <summary> /// <summary>
/// Gets the list of paid post media IDs to avoid duplicates. /// Gets the list of paid post media IDs to avoid duplicates.
/// </summary> /// </summary>
public List<long> PaidPostIds { get; } = new(); public List<long> PaidPostIds { get; } = [];
/// <summary> /// <summary>
/// Retrieves the available users and lists based on current configuration. /// Retrieves the available users and lists based on the current configuration.
/// </summary> /// </summary>
/// <returns>A result containing users, lists, and any errors.</returns> /// <returns>A result containing users, lists, and any errors.</returns>
public async Task<UserListResult> GetAvailableUsersAsync() public async Task<UserListResult> GetAvailableUsersAsync()
@ -235,9 +235,9 @@ public class DownloadOrchestrationService(
{ {
eventHandler.OnMessage("Getting Stories"); eventHandler.OnMessage("Getting Stories");
Dictionary<long, string>? tempStories = await apiService.GetMedia(MediaType.Stories, Dictionary<long, string>? tempStories = await apiService.GetMedia(MediaType.Stories,
$"/users/{userId}/stories", null, path, PaidPostIds); $"/users/{userId}/stories", null, path);
if (tempStories != null && tempStories.Count > 0) if (tempStories is { Count: > 0 })
{ {
eventHandler.OnContentFound("Stories", tempStories.Count, tempStories.Count); eventHandler.OnContentFound("Stories", tempStories.Count, tempStories.Count);
@ -263,9 +263,9 @@ public class DownloadOrchestrationService(
{ {
eventHandler.OnMessage("Getting Highlights"); eventHandler.OnMessage("Getting Highlights");
Dictionary<long, string>? tempHighlights = await apiService.GetMedia(MediaType.Highlights, Dictionary<long, string>? tempHighlights = await apiService.GetMedia(MediaType.Highlights,
$"/users/{userId}/stories/highlights", null, path, PaidPostIds); $"/users/{userId}/stories/highlights", null, path);
if (tempHighlights != null && tempHighlights.Count > 0) if (tempHighlights is { Count: > 0 })
{ {
eventHandler.OnContentFound("Highlights", tempHighlights.Count, tempHighlights.Count); eventHandler.OnContentFound("Highlights", tempHighlights.Count, tempHighlights.Count);

View File

@ -500,15 +500,9 @@ public class DownloadService(
client.DefaultRequestHeaders.Add("User-Agent", auth.UserAgent); client.DefaultRequestHeaders.Add("User-Agent", auth.UserAgent);
using HttpResponseMessage response = await client.GetAsync(mpdUrl, HttpCompletionOption.ResponseHeadersRead); using HttpResponseMessage response = await client.GetAsync(mpdUrl, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode) return response is { IsSuccessStatusCode: true, Content.Headers.LastModified: not null }
{ ? response.Content.Headers.LastModified.Value.DateTime
if (response.Content.Headers.LastModified != null) : DateTime.Now;
{
return response.Content.Headers.LastModified.Value.DateTime;
}
}
return DateTime.Now;
} }
/// <summary> /// <summary>
@ -842,7 +836,7 @@ public class DownloadService(
/// <param name="author">Author info.</param> /// <param name="author">Author info.</param>
/// <param name="users">Known users map.</param> /// <param name="users">Known users map.</param>
/// <returns>True when the media is newly downloaded.</returns> /// <returns>True when the media is newly downloaded.</returns>
public async Task<bool> DownloadMedia(string url, string folder, long mediaId, string apiType, private async Task<bool> DownloadMedia(string url, string folder, long mediaId, string apiType,
IProgressReporter progressReporter, string path, IProgressReporter progressReporter, string path,
string? filenameFormat, object? postInfo, object? postMedia, string? filenameFormat, object? postInfo, object? postMedia,
object? author, Dictionary<string, long> users) object? author, Dictionary<string, long> users)
@ -876,7 +870,7 @@ public class DownloadService(
/// <param name="author">Author info.</param> /// <param name="author">Author info.</param>
/// <param name="users">Known users map.</param> /// <param name="users">Known users map.</param>
/// <returns>True when the media is newly downloaded.</returns> /// <returns>True when the media is newly downloaded.</returns>
public async Task<bool> DownloadDrmVideo(string policy, string signature, string kvp, string url, private async Task<bool> DownloadDrmVideo(string policy, string signature, string kvp, string url,
string decryptionKey, string folder, DateTime lastModified, long mediaId, string apiType, string decryptionKey, string folder, DateTime lastModified, long mediaId, string apiType,
IProgressReporter progressReporter, string path, IProgressReporter progressReporter, string path,
string? filenameFormat, object? postInfo, object? postMedia, string? filenameFormat, object? postInfo, object? postMedia,
@ -1028,7 +1022,7 @@ public class DownloadService(
Log.Debug($"Calling DownloadHighlights - {username}"); Log.Debug($"Calling DownloadHighlights - {username}");
Dictionary<long, string>? highlights = await apiService.GetMedia(MediaType.Highlights, Dictionary<long, string>? highlights = await apiService.GetMedia(MediaType.Highlights,
$"/users/{userId}/stories/highlights", null, path, paidPostIds.ToList()); $"/users/{userId}/stories/highlights", null, path);
if (highlights == null || highlights.Count == 0) if (highlights == null || highlights.Count == 0)
{ {
@ -1091,7 +1085,7 @@ public class DownloadService(
Log.Debug($"Calling DownloadStories - {username}"); Log.Debug($"Calling DownloadStories - {username}");
Dictionary<long, string>? stories = await apiService.GetMedia(MediaType.Stories, $"/users/{userId}/stories", Dictionary<long, string>? stories = await apiService.GetMedia(MediaType.Stories, $"/users/{userId}/stories",
null, path, paidPostIds.ToList()); null, path);
if (stories == null || stories.Count == 0) if (stories == null || stories.Count == 0)
{ {

View File

@ -39,8 +39,7 @@ public interface IApiService
/// <summary> /// <summary>
/// Retrieves media URLs for stories or highlights. /// Retrieves media URLs for stories or highlights.
/// </summary> /// </summary>
Task<Dictionary<long, string>?> GetMedia(MediaType mediaType, string endpoint, string? username, string folder, Task<Dictionary<long, string>?> GetMedia(MediaType mediaType, string endpoint, string? username, string folder);
List<long> paidPostIds);
/// <summary> /// <summary>
/// Retrieves paid posts and their media. /// Retrieves paid posts and their media.

View File

@ -11,7 +11,7 @@ public interface IAuthService
Auth? CurrentAuth { get; set; } Auth? CurrentAuth { get; set; }
/// <summary> /// <summary>
/// Loads authentication data from disk. /// Loads authentication data from the disk.
/// </summary> /// </summary>
Task<bool> LoadFromFileAsync(string filePath = "auth.json"); Task<bool> LoadFromFileAsync(string filePath = "auth.json");

View File

@ -20,23 +20,6 @@ public interface IDownloadService
Task<bool> ProcessMediaDownload(string folder, long mediaId, string apiType, string url, string path, Task<bool> ProcessMediaDownload(string folder, long mediaId, string apiType, string url, string path,
string serverFileName, string resolvedFileName, string extension, IProgressReporter progressReporter); string serverFileName, string resolvedFileName, string extension, IProgressReporter progressReporter);
/// <summary>
/// Downloads a single media item.
/// </summary>
Task<bool> DownloadMedia(string url, string folder, long mediaId, string apiType,
IProgressReporter progressReporter, string path,
string? filenameFormat, object? postInfo, object? postMedia,
object? author, Dictionary<string, long> users);
/// <summary>
/// Downloads a DRM-protected video.
/// </summary>
Task<bool> DownloadDrmVideo(string policy, string signature, string kvp, string url,
string decryptionKey, string folder, DateTime lastModified, long mediaId, string apiType,
IProgressReporter progressReporter, string path,
string? filenameFormat, object? postInfo, object? postMedia,
object? author, Dictionary<string, long> users);
/// <summary> /// <summary>
/// Retrieves decryption information for a DRM media item. /// Retrieves decryption information for a DRM media item.
/// </summary> /// </summary>

View File

@ -11,10 +11,4 @@ public interface IProgressReporter
/// </summary> /// </summary>
/// <param name="increment">The amount to increment progress by</param> /// <param name="increment">The amount to increment progress by</param>
void ReportProgress(long increment); void ReportProgress(long increment);
/// <summary>
/// Reports a status message (optional for implementations).
/// </summary>
/// <param name="message">The status message to report</param>
void ReportStatus(string message);
} }

View File

@ -111,13 +111,13 @@ internal class HttpUtil
int retryCount = 0; int retryCount = 0;
while (retryCount < Constants.WIDEVINE_MAX_RETRIES && response.StatusCode == HttpStatusCode.TooManyRequests) while (retryCount < Constants.WidevineMaxRetries && response.StatusCode == HttpStatusCode.TooManyRequests)
{ {
// //
// We've hit a rate limit, so we should wait before retrying. // We've hit a rate limit, so we should wait before retrying.
// //
int retryAfterSeconds = int retryAfterSeconds =
Constants.WIDEVINE_RETRY_DELAY * (retryCount + 1); // Default retry time. Increases with each retry. Constants.WidevineRetryDelay * (retryCount + 1); // Default retry time. Increases with each retry.
if (response.Headers.RetryAfter != null && response.Headers.RetryAfter.Delta.HasValue) if (response.Headers.RetryAfter != null && response.Headers.RetryAfter.Delta.HasValue)
{ {
if (response.Headers.RetryAfter.Delta.Value.TotalSeconds > 0) if (response.Headers.RetryAfter.Delta.Value.TotalSeconds > 0)

View File

@ -11,10 +11,4 @@ public class SpectreProgressReporter(ProgressTask task) : IProgressReporter
private readonly ProgressTask _task = task ?? throw new ArgumentNullException(nameof(task)); private readonly ProgressTask _task = task ?? throw new ArgumentNullException(nameof(task));
public void ReportProgress(long increment) => _task.Increment(increment); public void ReportProgress(long increment) => _task.Increment(increment);
public void ReportStatus(string message)
{
// Optionally update task description or handle status messages
// For now, we'll leave this empty as the task description is set when creating the progress bar
}
} }