forked from sim0n00ps/OF-DL
Refactor services
This commit is contained in:
parent
70738fd4ae
commit
04004c7084
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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");
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user