diff --git a/Manager.App/Components/Pages/Channels.razor b/Manager.App/Components/Pages/Channels.razor
index ac9afce..b8887a4 100644
--- a/Manager.App/Components/Pages/Channels.razor
+++ b/Manager.App/Components/Pages/Channels.razor
@@ -29,9 +29,9 @@
Has login
- @context.Name
+ @context.Channel?.Name
@context.Id
- @(context.ClientAccount != null)
+ @(context.HttpCookies.Any())
No channels found
diff --git a/Manager.App/Components/Pages/Channels.razor.cs b/Manager.App/Components/Pages/Channels.razor.cs
index 968e75d..6c526ba 100644
--- a/Manager.App/Components/Pages/Channels.razor.cs
+++ b/Manager.App/Components/Pages/Channels.razor.cs
@@ -9,12 +9,12 @@ namespace Manager.App.Components.Pages;
public partial class Channels : ComponentBase
{
private readonly DialogOptions _dialogOptions = new() { BackdropClick = false, CloseButton = true, FullWidth = true, MaxWidth = MaxWidth.ExtraLarge };
- private MudTable? _table;
+ private MudTable? _table;
- private async Task> ServerReload(TableState state, CancellationToken token)
+ private async Task> ServerReload(TableState state, CancellationToken token)
{
- var results = await LibraryService.GetChannelsAsync(state.PageSize, state.Page * state.PageSize, token);
- return !results.IsSuccess ? new TableData() : new TableData { Items = results.Value, TotalItems = results.Total };
+ var results = await LibraryService.GetAccountsAsync(null, state.Page * state.PageSize, state.PageSize, token);
+ return !results.IsSuccess ? new TableData() : new TableData { Items = results.Value, TotalItems = results.Total };
}
private async Task OnAddAccountDialogAsync()
diff --git a/Manager.App/Services/ILibraryService.cs b/Manager.App/Services/ILibraryService.cs
index 2e26de2..87ee3b1 100644
--- a/Manager.App/Services/ILibraryService.cs
+++ b/Manager.App/Services/ILibraryService.cs
@@ -11,9 +11,8 @@ public interface ILibraryService
public Task FetchChannelImagesAsync(InnertubeChannel innertubeChannel);
public Task SaveClientAsync(ClientAccountEntity client, CancellationToken cancellationToken = default);
public Task> GetChannelByIdAsync(string id, CancellationToken cancellationToken = default);
-
public Task SaveChannelAsync(InnertubeChannel innertubeChannel, CancellationToken cancellationToken = default);
public Task> GetLibraryInfoAsync(CancellationToken cancellationToken = default);
-
- public Task> GetChannelsAsync(int total = 20, int offset = 0, CancellationToken cancellationToken = default);
+ public Task> GetAccountsAsync(string? search, int offset = 0, int total = 20, CancellationToken cancellationToken = default);
+ public Task> GetChannelsAsync(int offset = 0, int total = 20, CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/Manager.App/Services/LibraryService.cs b/Manager.App/Services/LibraryService.cs
index b47065e..c3e3643 100644
--- a/Manager.App/Services/LibraryService.cs
+++ b/Manager.App/Services/LibraryService.cs
@@ -61,7 +61,7 @@ public class LibraryService : ILibraryService
{
foreach (var image in images)
{
- if (context.Files.Any(f => image.Url.Equals(f.OriginalUrl, StringComparison.OrdinalIgnoreCase)))
+ if (context.Files.Any(f => image.Url.Equals(f.OriginalUrl)))
{
continue;
}
@@ -108,7 +108,7 @@ public class LibraryService : ILibraryService
await using var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
var updateEntity = false;
- var dbClient = context.ClientAccounts.FirstOrDefault(c => c.Id == client.Id);
+ var dbClient = context.ClientAccounts.Include(ca => ca.HttpCookies).FirstOrDefault(c => c.Id == client.Id);
if (dbClient == null)
{
dbClient = client;
@@ -245,13 +245,55 @@ public class LibraryService : ILibraryService
return HandleException(e);
}
}
+
+ public async Task> GetAccountsAsync(string? search, int offset = 0, int total = 20, CancellationToken cancellationToken = default)
+ {
+ if (total == 0)
+ {
+ total = 20;
+ }
- public async Task> GetChannelsAsync(int total = 20, int offset = 0, CancellationToken cancellationToken = default)
+ try
+ {
+ await using var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
+ var accounts = context.ClientAccounts
+ .Include(ca => ca.Channel)
+ .Include(ca => ca.HttpCookies)
+ .OrderByDescending(ca => ca.Id);
+ var totalAccounts = accounts.Count();
+
+ if (!string.IsNullOrWhiteSpace(search) && totalAccounts != 0)
+ {
+ var normalizedSearch = $"%{search.ToLower()}%";
+ var searched = accounts
+ .Where(ca =>
+ EF.Functions.Like(
+ (
+ ca.Id.ToString() + " " +
+ (ca.Channel != null ? ca.Channel.Name : "") + " " +
+ (ca.Channel != null ? ca.Channel.Handle : "")
+ ).ToLower(),
+ normalizedSearch
+ )
+ );
+ totalAccounts = searched.Count();
+ accounts = searched.OrderByDescending(ca => ca.Id);
+ }
+
+ return new ListResultReturn(totalAccounts == 0 ? [] : accounts.Skip(offset).Take(total).ToList(), totalAccounts);
+ }
+ catch (Exception e)
+ {
+ return ResultError.Error(e);
+ }
+ }
+
+ public async Task> GetChannelsAsync(int offset = 0, int total = 20, CancellationToken cancellationToken = default)
{
try
{
await using var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
- var orderedAccounts = context.Channels.Include(x => x.ClientAccount).Where(x => x.ClientAccount != null).OrderBy(x => x.Id);
+ var orderedAccounts = context.Channels.Include(x => x.ClientAccount).OrderBy(x => x.Id);
return new ListResultReturn(orderedAccounts.Skip(offset).Take(total).ToList(),orderedAccounts.Count());
}
catch (Exception e)
diff --git a/Manager.App/Services/System/ClientService.cs b/Manager.App/Services/System/ClientService.cs
index 4129087..34c642c 100644
--- a/Manager.App/Services/System/ClientService.cs
+++ b/Manager.App/Services/System/ClientService.cs
@@ -105,8 +105,23 @@ public class ClientService(IServiceScopeFactory scopeFactory, ILogger httpCookies = [];
+ httpCookies.AddRange(client.CookieContainer.GetAllCookies()
+ .ToList()
+ .Select(cookie => new HttpCookieEntity
+ {
+ ClientId = client.Id,
+ Name = cookie.Name,
+ Value = cookie.Value,
+ Domain = cookie.Domain,
+ Path = cookie.Path,
+ Secure = cookie.Secure,
+ HttpOnly = cookie.HttpOnly,
+ ExpiresUtc = cookie.Expires
+ }));
- var saveResult = await _libraryService.SaveClientAsync(new ClientAccountEntity { Id = client.Id, UserAgent = client.UserAgent }, cancellationToken);
+ var saveResult = await _libraryService.SaveClientAsync(new ClientAccountEntity { Id = client.Id, UserAgent = client.UserAgent, HttpCookies = httpCookies }, cancellationToken);
return saveResult;
}
}
\ No newline at end of file
diff --git a/Manager.Data/Contexts/LibraryDbContext.cs b/Manager.Data/Contexts/LibraryDbContext.cs
index c642195..69256d5 100644
--- a/Manager.Data/Contexts/LibraryDbContext.cs
+++ b/Manager.Data/Contexts/LibraryDbContext.cs
@@ -55,8 +55,9 @@ public sealed class LibraryDbContext : DbContext
.WithOne()
.HasForeignKey(x => x.ChannelId);
channel.HasOne(x => x.ClientAccount)
- .WithOne()
- .HasForeignKey(e => e.Id);
+ .WithOne(x => x.Channel)
+ .HasForeignKey(e => e.Id)
+ .IsRequired(false);
});
modelBuilder.Entity(cae =>
@@ -66,6 +67,10 @@ public sealed class LibraryDbContext : DbContext
cae.HasMany(x => x.HttpCookies)
.WithOne()
.HasForeignKey(x => x.ClientId);
+ cae.HasOne(x => x.Channel)
+ .WithOne(ca => ca.ClientAccount)
+ .HasForeignKey(ce => ce.Id)
+ .IsRequired(false);
});
modelBuilder.Entity(httpce =>
diff --git a/Manager.Data/Entities/LibraryContext/ClientAccountEntity.cs b/Manager.Data/Entities/LibraryContext/ClientAccountEntity.cs
index 10c9ae4..8c30f15 100644
--- a/Manager.Data/Entities/LibraryContext/ClientAccountEntity.cs
+++ b/Manager.Data/Entities/LibraryContext/ClientAccountEntity.cs
@@ -11,4 +11,5 @@ public class ClientAccountEntity : DateTimeBase
public List HttpCookies { get; set; } = [];
[MaxLength(DataConstants.DbContext.DefaultDbStringSize)]
public string? UserAgent { get; set; }
+ public ChannelEntity? Channel { get; set; }
}
\ No newline at end of file