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)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -572,11 +572,13 @@ 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")
{ {
columnExists = true; continue;
break;
} }
columnExists = true;
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.
@ -125,7 +124,7 @@ public interface IApiService
Task<Dictionary<string, long>?> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions); Task<Dictionary<string, long>?> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions);
/// <summary> /// <summary>
/// Retrieves a decryption key via the OFDL fallback service. /// Retrieves a decryption key via the OF DL fallback service.
/// </summary> /// </summary>
Task<string> GetDecryptionKeyOfdl(Dictionary<string, string> drmHeaders, string licenceUrl, string pssh); Task<string> GetDecryptionKeyOfdl(Dictionary<string, string> drmHeaders, string licenceUrl, string pssh);
} }

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
}
} }