forked from sim0n00ps/OF-DL
Compare commits
No commits in common. "a7906f84f9e33c75139393dedf9eb1f726baa45a" and "6054d3b6a2332052bd44211f59877321c38763f3" have entirely different histories.
a7906f84f9
...
6054d3b6a2
@ -2,12 +2,7 @@ using OF_DL.Models.Downloads;
|
||||
|
||||
namespace OF_DL.CLI;
|
||||
|
||||
public interface ICajetanDownloadEventHandler : IDownloadEventHandler
|
||||
{
|
||||
void OnMessage(string message, string color);
|
||||
}
|
||||
|
||||
public class CajetanDownloadEventHandler : ICajetanDownloadEventHandler
|
||||
internal class CajetanDownloadEventHandler : IDownloadEventHandler
|
||||
{
|
||||
private readonly SpectreDownloadEventHandler _eventHandler = new();
|
||||
|
||||
@ -20,9 +15,6 @@ public class CajetanDownloadEventHandler : ICajetanDownloadEventHandler
|
||||
public void OnMessage(string message)
|
||||
=> _eventHandler.OnMessage(message);
|
||||
|
||||
public void OnMessage(string message, string color)
|
||||
=> AnsiConsole.Markup($"[{color.ToLowerInvariant()}]{Markup.Escape(message)}\n[/]");
|
||||
|
||||
public void OnNoContentFound(string contentType)
|
||||
=> _eventHandler.OnNoContentFound(contentType);
|
||||
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
namespace OF_DL.Models.Dtos.Messages;
|
||||
|
||||
public class ChatsDto
|
||||
{
|
||||
[JsonProperty("list")] public List<ChatItemDto> List { get; set; } = [];
|
||||
[JsonProperty("hasMore")] public bool HasMore { get; set; }
|
||||
[JsonProperty("nextOffset")] public int NextOffset { get; set; }
|
||||
}
|
||||
|
||||
public class ChatItemDto
|
||||
{
|
||||
[JsonProperty("withUser")] public ChatUserDto WithUser { get; set; } = new();
|
||||
[JsonProperty("unreadMessagesCount")] public int UnreadMessagesCount { get; set; }
|
||||
}
|
||||
|
||||
public class ChatUserDto
|
||||
{
|
||||
[JsonProperty("id")] public long Id { get; set; }
|
||||
}
|
||||
@ -3,10 +3,7 @@ using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
AnsiConsole.Write(new FigletText("Welcome to OF-DL").Color(Color.Red));
|
||||
await RunAsync(args);
|
||||
|
||||
static async Task RunAsync(string[] args)
|
||||
{
|
||||
ServiceCollection services = await ConfigureServices(args);
|
||||
ServiceProvider serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
@ -14,7 +11,6 @@ static async Task RunAsync(string[] args)
|
||||
|
||||
Worker worker = serviceProvider.GetRequiredService<Worker>();
|
||||
await worker.RunAsync();
|
||||
}
|
||||
|
||||
static async Task<ServiceCollection> ConfigureServices(string[] args)
|
||||
{
|
||||
@ -66,11 +62,6 @@ static async Task<ServiceCollection> ConfigureServices(string[] args)
|
||||
services.AddSingleton(cajetanConfig);
|
||||
|
||||
services.AddSingleton<IAuthService, AuthService>();
|
||||
services.AddSingleton<IStartupService, StartupService>();
|
||||
services.AddSingleton<IFileNameService, FileNameService>();
|
||||
|
||||
services.AddSingleton<ICajetanDownloadService, CajetanDownloadService>();
|
||||
services.AddSingleton<IDownloadService>(sp => sp.GetRequiredService<ICajetanDownloadService>());
|
||||
|
||||
services.AddSingleton<ICajetanApiService, CajetanApiService>();
|
||||
services.AddSingleton<IApiService>(sp => sp.GetRequiredService<ICajetanApiService>());
|
||||
@ -78,12 +69,10 @@ static async Task<ServiceCollection> ConfigureServices(string[] args)
|
||||
services.AddSingleton<ICajetanDbService, CajetanDbService>();
|
||||
services.AddSingleton<IDbService>(sp => sp.GetRequiredService<ICajetanDbService>());
|
||||
|
||||
|
||||
services.AddSingleton<ICajetanDownloadOrchestrationService, CajetanDownloadOrchestrationService>();
|
||||
services.AddSingleton<IDownloadOrchestrationService>(sp => sp.GetRequiredService<ICajetanDownloadOrchestrationService>());
|
||||
|
||||
services.AddSingleton<ICajetanDownloadEventHandler, CajetanDownloadEventHandler>();
|
||||
services.AddSingleton<IDownloadEventHandler>(sp => sp.GetRequiredService<ICajetanDownloadEventHandler>());
|
||||
services.AddSingleton<IDownloadService, DownloadService>();
|
||||
services.AddSingleton<IFileNameService, FileNameService>();
|
||||
services.AddSingleton<IStartupService, StartupService>();
|
||||
services.AddSingleton<IDownloadOrchestrationService, DownloadOrchestrationService>();
|
||||
|
||||
services.AddSingleton<Worker>();
|
||||
|
||||
|
||||
@ -2,10 +2,11 @@ global using Serilog;
|
||||
global using Spectre.Console;
|
||||
global using OF_DL;
|
||||
global using OF_DL.CLI;
|
||||
global using OF_DL.Crypto;
|
||||
global using OF_DL.Enumerations;
|
||||
global using OF_DL.Exceptions;
|
||||
global using OF_DL.Helpers;
|
||||
global using OF_DL.Models;
|
||||
global using OF_DL.Models.Config;
|
||||
global using OF_DL.Services;
|
||||
global using Newtonsoft.Json;
|
||||
global using OF_DL.Utils;
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
using MessageDtos = OF_DL.Models.Dtos.Messages;
|
||||
using MessageEntities = OF_DL.Models.Entities.Messages;
|
||||
using Newtonsoft.Json;
|
||||
using UserDtos = OF_DL.Models.Dtos.Users;
|
||||
using UserEntities = OF_DL.Models.Entities.Users;
|
||||
|
||||
namespace OF_DL.Services;
|
||||
|
||||
public class CajetanApiService(IAuthService authService, IConfigService configService, ICajetanDbService dbService, ICajetanDownloadEventHandler eventHandler)
|
||||
public interface ICajetanApiService : IApiService
|
||||
{
|
||||
Task<UserEntities.UserInfo?> GetDetailedUserInfo(string endpoint);
|
||||
}
|
||||
|
||||
public class CajetanApiService(IAuthService authService, IConfigService configService, ICajetanDbService dbService)
|
||||
: ApiService(authService, configService, dbService), ICajetanApiService
|
||||
{
|
||||
private readonly ICajetanDownloadEventHandler _eventHandler = eventHandler;
|
||||
|
||||
public new async Task<UserEntities.User?> GetUserInfo(string endpoint)
|
||||
{
|
||||
UserEntities.UserInfo? userInfo = await GetDetailedUserInfo(endpoint);
|
||||
@ -20,6 +22,11 @@ public class CajetanApiService(IAuthService authService, IConfigService configSe
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves detailed user information from the API.
|
||||
/// </summary>
|
||||
/// <param name="endpoint">The user endpoint.</param>
|
||||
/// <returns>The user entity when available.</returns>
|
||||
public async Task<UserEntities.UserInfo?> GetDetailedUserInfo(string endpoint)
|
||||
{
|
||||
Log.Debug($"Calling GetDetailedUserInfo: {endpoint}");
|
||||
@ -57,133 +64,6 @@ public class CajetanApiService(IAuthService authService, IConfigService configSe
|
||||
return null;
|
||||
}
|
||||
|
||||
public new async Task<MessageEntities.MessageCollection> GetMessages(string endpoint, string folder, IStatusReporter statusReporter)
|
||||
{
|
||||
(bool couldExtract, long userId) = ExtractUserId(endpoint);
|
||||
|
||||
_eventHandler.OnMessage("Getting Unread Chats", "grey");
|
||||
HashSet<long> usersWithUnread = couldExtract ? await GetUsersWithUnreadMessagesAsync() : [];
|
||||
|
||||
MessageEntities.MessageCollection messages = await base.GetMessages(endpoint, folder, statusReporter);
|
||||
|
||||
if (usersWithUnread.Contains(userId))
|
||||
{
|
||||
_eventHandler.OnMessage("Restoring unread state", "grey");
|
||||
await MarkAsUnreadAsync($"chats/{userId}/mark-as-read");
|
||||
}
|
||||
|
||||
return messages;
|
||||
|
||||
static (bool couldExtract, long userId) ExtractUserId(string endpoint)
|
||||
{
|
||||
string withoutChatsAndMessages = endpoint
|
||||
.Replace("chats", "", StringComparison.OrdinalIgnoreCase)
|
||||
.Replace("messages", "", StringComparison.OrdinalIgnoreCase);
|
||||
string trimmed = withoutChatsAndMessages.Trim(' ', '/', '\\');
|
||||
|
||||
if (long.TryParse(trimmed, out long userId))
|
||||
return (true, userId);
|
||||
|
||||
return (false, default);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<HashSet<long>> GetUsersWithUnreadMessagesAsync()
|
||||
{
|
||||
MessageDtos.ChatsDto unreadChats = await GetChatsAsync("", onlyUnread: true);
|
||||
HashSet<long> userWithUnread = [];
|
||||
|
||||
foreach (MessageDtos.ChatItemDto chatItem in unreadChats.List)
|
||||
{
|
||||
if (chatItem?.WithUser?.Id is null)
|
||||
continue;
|
||||
|
||||
if (chatItem.UnreadMessagesCount <= 0)
|
||||
continue;
|
||||
|
||||
userWithUnread.Add(chatItem.WithUser.Id);
|
||||
}
|
||||
|
||||
return userWithUnread;
|
||||
}
|
||||
|
||||
public async Task MarkAsUnreadAsync(string endpoint)
|
||||
{
|
||||
Log.Debug($"Calling MarkAsUnread - {endpoint}");
|
||||
|
||||
try
|
||||
{
|
||||
var result = new { success = false };
|
||||
|
||||
string? body = await BuildHeaderAndExecuteRequests([], endpoint, GetHttpClient(), HttpMethod.Delete);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(body))
|
||||
result = JsonConvert.DeserializeAnonymousType(body, result);
|
||||
|
||||
if (result?.success != true)
|
||||
_eventHandler.OnMessage($"Failed to mark chat as unread! Endpoint: {endpoint}", "yellow");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionLoggerHelper.LogException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<MessageDtos.ChatsDto> GetChatsAsync(string endpoint, bool onlyUnread)
|
||||
{
|
||||
Log.Debug($"Calling GetChats - {endpoint}");
|
||||
|
||||
MessageDtos.ChatsDto allChats = new();
|
||||
|
||||
try
|
||||
{
|
||||
int limit = 60;
|
||||
Dictionary<string, string> getParams = new()
|
||||
{
|
||||
{ "limit", $"{limit}" },
|
||||
{ "offset", "0" },
|
||||
{ "skip_users", "all" },
|
||||
{ "order", "recent" }
|
||||
};
|
||||
|
||||
if (onlyUnread)
|
||||
getParams["filter"] = "unread";
|
||||
|
||||
string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient());
|
||||
MessageDtos.ChatsDto? chats = DeserializeJson<MessageDtos.ChatsDto>(body, s_mJsonSerializerSettings);
|
||||
|
||||
if (chats is null)
|
||||
return allChats;
|
||||
|
||||
if (chats.HasMore)
|
||||
{
|
||||
getParams["offset"] = $"{chats.NextOffset}";
|
||||
|
||||
while (true)
|
||||
{
|
||||
string? loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient());
|
||||
MessageDtos.ChatsDto? newChats = DeserializeJson<MessageDtos.ChatsDto>(loopbody, s_mJsonSerializerSettings);
|
||||
|
||||
if (newChats is null)
|
||||
break;
|
||||
|
||||
allChats.List.AddRange(newChats.List);
|
||||
|
||||
if (!newChats.HasMore)
|
||||
break;
|
||||
|
||||
getParams["offset"] = $"{newChats.NextOffset}";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionLoggerHelper.LogException(ex);
|
||||
}
|
||||
|
||||
return allChats;
|
||||
}
|
||||
|
||||
private static UserEntities.UserInfo FromDto(UserDtos.UserDto? userDto)
|
||||
{
|
||||
if (userDto is null)
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
namespace OF_DL.Services;
|
||||
|
||||
public class CajetanDownloadOrchestrationService(ICajetanApiService apiService, IConfigService configService, ICajetanDownloadService downloadService, ICajetanDbService dbService)
|
||||
: DownloadOrchestrationService(apiService, configService, downloadService, dbService), ICajetanDownloadOrchestrationService
|
||||
{
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace OF_DL.Services;
|
||||
|
||||
public class CajetanDownloadService(IAuthService authService, IConfigService configService, ICajetanDbService dbService, IFileNameService fileNameService, ICajetanApiService apiService)
|
||||
: DownloadService(authService, configService, dbService, fileNameService, apiService), ICajetanDownloadService
|
||||
{
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
using UserEntities = OF_DL.Models.Entities.Users;
|
||||
|
||||
namespace OF_DL.Services;
|
||||
|
||||
public interface ICajetanApiService : IApiService
|
||||
{
|
||||
Task<UserEntities.UserInfo?> GetDetailedUserInfo(string endpoint);
|
||||
|
||||
Task<HashSet<long>> GetUsersWithUnreadMessagesAsync();
|
||||
Task MarkAsUnreadAsync(string endpoint);
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace OF_DL.Services;
|
||||
|
||||
public interface ICajetanDownloadOrchestrationService : IDownloadOrchestrationService
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace OF_DL.Services;
|
||||
|
||||
public interface ICajetanDownloadService : IDownloadService
|
||||
{
|
||||
|
||||
}
|
||||
@ -2772,12 +2772,12 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
||||
}
|
||||
|
||||
|
||||
protected async Task<string?> BuildHeaderAndExecuteRequests(Dictionary<string, string> getParams, string endpoint,
|
||||
HttpClient client, HttpMethod? method = null)
|
||||
private async Task<string?> BuildHeaderAndExecuteRequests(Dictionary<string, string> getParams, string endpoint,
|
||||
HttpClient client)
|
||||
{
|
||||
Log.Debug("Calling BuildHeaderAndExecuteRequests");
|
||||
|
||||
HttpRequestMessage request = await BuildHttpRequestMessage(getParams, endpoint, method);
|
||||
HttpRequestMessage request = await BuildHttpRequestMessage(getParams, endpoint);
|
||||
using HttpResponseMessage response = await client.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
string body = await response.Content.ReadAsStringAsync();
|
||||
@ -2789,18 +2789,15 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
||||
|
||||
|
||||
protected Task<HttpRequestMessage> BuildHttpRequestMessage(Dictionary<string, string> getParams,
|
||||
string endpoint, HttpMethod? method = null)
|
||||
string endpoint)
|
||||
{
|
||||
Log.Debug("Calling BuildHttpRequestMessage");
|
||||
|
||||
string queryParams = "";
|
||||
|
||||
if (getParams.Count != 0)
|
||||
queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
string queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
|
||||
Dictionary<string, string> headers = GetDynamicHeaders($"/api2/v2{endpoint}", queryParams);
|
||||
|
||||
HttpRequestMessage request = new(method ?? HttpMethod.Get, $"{Constants.ApiUrl}{endpoint}{queryParams}");
|
||||
HttpRequestMessage request = new(HttpMethod.Get, $"{Constants.ApiUrl}{endpoint}{queryParams}");
|
||||
|
||||
Log.Debug($"Full request URL: {Constants.ApiUrl}{endpoint}{queryParams}");
|
||||
|
||||
@ -2824,7 +2821,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
||||
private static bool IsStringOnlyDigits(string input) => input.All(char.IsDigit);
|
||||
|
||||
|
||||
protected HttpClient GetHttpClient()
|
||||
private HttpClient GetHttpClient()
|
||||
{
|
||||
HttpClient client = new();
|
||||
if (configService.CurrentConfig.Timeout is > 0)
|
||||
@ -2835,7 +2832,7 @@ public class ApiService(IAuthService authService, IConfigService configService,
|
||||
return client;
|
||||
}
|
||||
|
||||
protected static T? DeserializeJson<T>(string? body, JsonSerializerSettings? settings = null)
|
||||
private static T? DeserializeJson<T>(string? body, JsonSerializerSettings? settings = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(body))
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user