Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/AStar.Dev.Infrastructure.FilesDb/Data/FilesContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using AStar.Dev.Infrastructure.FilesDb.Models;
using AStar.Dev.Infrastructure.FilesDb.Models;
using Microsoft.EntityFrameworkCore;

namespace AStar.Dev.Infrastructure.FilesDb.Data;
Expand Down Expand Up @@ -76,7 +76,11 @@ public FilesContext()
public DbSet<DownloadedFileClassification> DownloadedFileClassifications { get; set; } = null!;

/// <inheritdoc />
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => _ = optionsBuilder.UseSqlite("Data Source=/home/jbarden/Documents/Scrapper/files.db");
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if(!optionsBuilder.IsConfigured)
_ = optionsBuilder.UseSqlite("Data Source=/home/jbarden/Documents/Scrapper/files.db");
}

/// <summary>
/// The overridden OnModelCreating method
Expand Down
1 change: 1 addition & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public override void OnFrameworkInitializationCompleted()
.AddTransient<SearchResultsPageFunctional>()
.AddTransient<IImportExportService, ImportExportService>()
.AddTransient<IFileSystem, RealFileSystem>()
.AddTransient<ScrapeConfigurationService>()
.AddTransient<Func<ScrapeConfigurationView>>(sp => () => sp.GetRequiredService<ScrapeConfigurationView>())
.AddTransient<MainWindow>();

Expand Down
3 changes: 3 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/ApplicationMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ public static class ApplicationMetadata
{
public const string Name = "AStar.Dev.Wallpaper.Scrapper";
public const string Version = "1.0.0";
public const string Redacted = "REDACTED";

public static string ApplicationFolder => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!.CombinePath("..", "..", "..");

public static string FileClassificationsExportFilePath => SpecialDirectories.MyDocuments.CombinePath("Scrapper", "FileClassifications.json");

public static string ScrapeConfigurationExportFilePath => SpecialDirectories.MyDocuments.CombinePath("Scrapper", "ScrapeConfiguration.json");
public static string ScrapedTagsExportFilePath => SpecialDirectories.MyDocuments.CombinePath("Scrapper", "ScrapedTags.json");
}
6 changes: 6 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/DTOs/ConnectionStringsDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public sealed record ConnectionStringsDto
{
public string Sqlite { get; init; } = string.Empty;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public sealed record ScrapeConfigurationDto
{
public ConnectionStringsDto ConnectionStrings { get; init; } = new();
public UserConfigurationDto UserConfiguration { get; init; } = new();
public SearchConfigurationDto SearchConfiguration { get; init; } = new();
public ScrapeDirectoriesDto ScrapeDirectories { get; init; } = new();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using ScrapeConfigurationEntityDomain = AStar.Dev.Infrastructure.FilesDb.Models.ScrapeConfigurationEntity;
using SearchCategoriesDomain = AStar.Dev.Infrastructure.FilesDb.Models.SearchCategories;
using ConnectionStringsDomain = AStar.Dev.Infrastructure.FilesDb.Models.ConnectionStrings;
using UserConfigurationDomain = AStar.Dev.Infrastructure.FilesDb.Models.UserConfiguration;
using SearchConfigurationDomain = AStar.Dev.Infrastructure.FilesDb.Models.SearchConfiguration;
using ScrapeDirectoriesDomain = AStar.Dev.Infrastructure.FilesDb.Models.ScrapeDirectories;

namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public static class ScrapeConfigurationDtoExtensions
{
public static ScrapeConfigurationDto ToDto(this ScrapeConfigurationEntityDomain entity) => new()
{
ConnectionStrings = new ConnectionStringsDto { Sqlite = entity.ConnectionStrings.Sqlite },
UserConfiguration = new UserConfigurationDto
{
LoginEmailAddress = entity.UserConfiguration.LoginEmailAddress,
Username = entity.UserConfiguration.Username,
Password = ApplicationMetadata.Redacted,
SessionCookie = ApplicationMetadata.Redacted
},
SearchConfiguration = new SearchConfigurationDto
{
BaseUrl = entity.SearchConfiguration.BaseUrl,
ApiKey = ApplicationMetadata.Redacted,
SearchCategories = [.. entity.SearchConfiguration.SearchCategories.Select(c => new SearchCategoryDto
{
Id = c.Id,
Name = c.Name,
LastKnownImageCount = c.LastKnownImageCount,
LastPageVisited = c.LastPageVisited,
TotalPages = c.TotalPages,
IncludeInSearch = c.IncludeInSearch
})],
SearchString = entity.SearchConfiguration.SearchString,
TopWallpapers = entity.SearchConfiguration.TopWallpapers,
SearchStringPrefix = entity.SearchConfiguration.SearchStringPrefix,
SearchStringSuffix = entity.SearchConfiguration.SearchStringSuffix,
Subscriptions = entity.SearchConfiguration.Subscriptions,
ImagePauseInSeconds = entity.SearchConfiguration.ImagePauseInSeconds,
StartingPageNumber = entity.SearchConfiguration.StartingPageNumber,
TotalPages = entity.SearchConfiguration.TotalPages,
SubscriptionsStartingPageNumber = entity.SearchConfiguration.SubscriptionsStartingPageNumber,
SubscriptionsTotalPages = entity.SearchConfiguration.SubscriptionsTotalPages,
TopWallpapersTotalPages = entity.SearchConfiguration.TopWallpapersTotalPages,
TopWallpapersStartingPageNumber = entity.SearchConfiguration.TopWallpapersStartingPageNumber,
LoginUrl = entity.SearchConfiguration.LoginUrl,
UseHeadless = entity.SearchConfiguration.UseHeadless,
SlowMotionDelay = entity.SearchConfiguration.SlowMotionDelay
},
ScrapeDirectories = new ScrapeDirectoriesDto
{
RootDirectory = entity.ScrapeDirectories.RootDirectory,
BaseSaveDirectory = entity.ScrapeDirectories.BaseSaveDirectory,
BaseDirectory = entity.ScrapeDirectories.BaseDirectory,
BaseDirectoryFamous = entity.ScrapeDirectories.BaseDirectoryFamous,
SubDirectoryName = entity.ScrapeDirectories.SubDirectoryName
}
};

public static ScrapeConfigurationEntityDomain ToDomain(this ScrapeConfigurationDto dto) => new()
{
ConnectionStrings = new ConnectionStringsDomain { Sqlite = dto.ConnectionStrings.Sqlite },
UserConfiguration = new UserConfigurationDomain
{
LoginEmailAddress = dto.UserConfiguration.LoginEmailAddress,
Username = dto.UserConfiguration.Username,
Password = dto.UserConfiguration.Password,
SessionCookie = dto.UserConfiguration.SessionCookie
},
SearchConfiguration = new SearchConfigurationDomain
{
BaseUrl = dto.SearchConfiguration.BaseUrl,
ApiKey = dto.SearchConfiguration.ApiKey,
SearchCategories = [.. dto.SearchConfiguration.SearchCategories.Select(c => new SearchCategoriesDomain
{
Id = c.Id,
Name = c.Name,
LastKnownImageCount = c.LastKnownImageCount,
LastPageVisited = c.LastPageVisited,
TotalPages = c.TotalPages,
IncludeInSearch = c.IncludeInSearch
})],
SearchString = dto.SearchConfiguration.SearchString,
TopWallpapers = dto.SearchConfiguration.TopWallpapers,
SearchStringPrefix = dto.SearchConfiguration.SearchStringPrefix,
SearchStringSuffix = dto.SearchConfiguration.SearchStringSuffix,
Subscriptions = dto.SearchConfiguration.Subscriptions,
ImagePauseInSeconds = dto.SearchConfiguration.ImagePauseInSeconds,
StartingPageNumber = dto.SearchConfiguration.StartingPageNumber,
TotalPages = dto.SearchConfiguration.TotalPages,
SubscriptionsStartingPageNumber = dto.SearchConfiguration.SubscriptionsStartingPageNumber,
SubscriptionsTotalPages = dto.SearchConfiguration.SubscriptionsTotalPages,
TopWallpapersTotalPages = dto.SearchConfiguration.TopWallpapersTotalPages,
TopWallpapersStartingPageNumber = dto.SearchConfiguration.TopWallpapersStartingPageNumber,
LoginUrl = dto.SearchConfiguration.LoginUrl,
UseHeadless = dto.SearchConfiguration.UseHeadless,
SlowMotionDelay = dto.SearchConfiguration.SlowMotionDelay
},
ScrapeDirectories = new ScrapeDirectoriesDomain
{
RootDirectory = dto.ScrapeDirectories.RootDirectory,
BaseSaveDirectory = dto.ScrapeDirectories.BaseSaveDirectory,
BaseDirectory = dto.ScrapeDirectories.BaseDirectory,
BaseDirectoryFamous = dto.ScrapeDirectories.BaseDirectoryFamous,
SubDirectoryName = dto.ScrapeDirectories.SubDirectoryName
}
};
}
10 changes: 10 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/DTOs/ScrapeDirectoriesDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public sealed record ScrapeDirectoriesDto
{
public string RootDirectory { get; init; } = string.Empty;
public string BaseSaveDirectory { get; init; } = string.Empty;
public string BaseDirectory { get; init; } = string.Empty;
public string BaseDirectoryFamous { get; init; } = string.Empty;
public string SubDirectoryName { get; init; } = string.Empty;
}
11 changes: 11 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/DTOs/SearchCategoryDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public sealed record SearchCategoryDto
{
public string Id { get; init; } = string.Empty;
public string Name { get; init; } = string.Empty;
public int LastKnownImageCount { get; init; }
public int LastPageVisited { get; init; }
public int TotalPages { get; init; }
public bool IncludeInSearch { get; init; } = true;
}
23 changes: 23 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/DTOs/SearchConfigurationDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public sealed record SearchConfigurationDto
{
public string BaseUrl { get; init; } = string.Empty;
public string ApiKey { get; init; } = string.Empty;
public List<SearchCategoryDto> SearchCategories { get; init; } = [];
public string SearchString { get; init; } = string.Empty;
public string TopWallpapers { get; init; } = string.Empty;
public string SearchStringPrefix { get; init; } = string.Empty;
public string SearchStringSuffix { get; init; } = string.Empty;
public string Subscriptions { get; init; } = string.Empty;
public int ImagePauseInSeconds { get; init; }
public int StartingPageNumber { get; init; }
public int TotalPages { get; init; }
public int SubscriptionsStartingPageNumber { get; init; }
public int SubscriptionsTotalPages { get; init; }
public int TopWallpapersTotalPages { get; init; }
public int TopWallpapersStartingPageNumber { get; init; }
public string LoginUrl { get; init; } = string.Empty;
public bool UseHeadless { get; init; }
public float? SlowMotionDelay { get; init; }
}
9 changes: 9 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/DTOs/UserConfigurationDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace AStar.Dev.Wallpaper.Scrapper.DTOs;

public sealed record UserConfigurationDto
{
public string LoginEmailAddress { get; init; } = string.Empty;
public string Username { get; init; } = string.Empty;
public string Password { get; init; } = string.Empty;
public string SessionCookie { get; init; } = string.Empty;
}
2 changes: 2 additions & 0 deletions src/AStar.Dev.Wallpaper.Scrapper/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<Button x:Name="ScrapeSiteNewButton" Content="Scrape Site New" Click="OnScrapeSiteFunctionalClicked" />
<Button x:Name="ExportButton" Content="Export Classifications" Click="OnExportClicked" />
<Button x:Name="ImportButton" Content="Import Classifications" Click="OnImportClicked" />
<Button x:Name="ExportScrapeConfigButton" Content="Export Config" Click="OnExportScrapeConfigClicked" />
<Button x:Name="ImportScrapeConfigButton" Content="Import Config" Click="OnImportScrapeConfigClicked" />
<Button x:Name="ExportTagsButton" Content="Export Tags" Click="OnExportTagsClicked" />
<Button x:Name="ImportTagsButton" Content="Import Tags" Click="OnImportTagsClicked" />
<Button x:Name="CancelButton" Content="Cancel" Click="OnCancelClicked" IsEnabled="False" />
Expand Down
41 changes: 40 additions & 1 deletion src/AStar.Dev.Wallpaper.Scrapper/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ public partial class MainWindow : Window, IDisposable
private readonly SearchWorkflowFunctional imagePageServiceFunctional;
private readonly SearchWorkflowFunctional searchWorkflowFunctional;
private readonly IFileSystem fileSystem;
private readonly ScrapeConfigurationService scrapeConfigurationService;
private CancellationTokenSource? cts;
private readonly Logger scrapeLogger;

public MainWindow(Func<ScrapeConfigurationView> scrapeConfigViewFactory, SearchWorkflowFunctional imagePageServiceFunctional, IFileSystem fileSystem, IPlaywrightService playwrightService, ScrapeConfiguration scrapeConfiguration, SearchWorkflowFunctional searchWorkflowFunctional, Logger logger, IScrapedTagRepository scrapedTagRepository, IFileDetailRepository fileDetailRepository, FileClassificationService fileClassificationService, IScrapedTagService scrapedTagService, ConfigurationSaver configurationSaver, TagsToIgnoreCompletely tagsToIgnoreCompletely, TagsTextToIgnore tagsTextToIgnore, IImportExportService importExportService)
public MainWindow(Func<ScrapeConfigurationView> scrapeConfigViewFactory, SearchWorkflowFunctional imagePageServiceFunctional, IFileSystem fileSystem, IPlaywrightService playwrightService, ScrapeConfiguration scrapeConfiguration, SearchWorkflowFunctional searchWorkflowFunctional, Logger logger, IScrapedTagRepository scrapedTagRepository, IFileDetailRepository fileDetailRepository, FileClassificationService fileClassificationService, IScrapedTagService scrapedTagService, ConfigurationSaver configurationSaver, TagsToIgnoreCompletely tagsToIgnoreCompletely, TagsTextToIgnore tagsTextToIgnore, IImportExportService importExportService, ScrapeConfigurationService scrapeConfigurationService)
{
this.scrapeConfigViewFactory = scrapeConfigViewFactory;
this.scrapeConfiguration = scrapeConfiguration;
Expand All @@ -56,6 +57,7 @@ public MainWindow(Func<ScrapeConfigurationView> scrapeConfigViewFactory, SearchW
this.imagePageServiceFunctional = imagePageServiceFunctional;
this.searchWorkflowFunctional = searchWorkflowFunctional;
this.fileSystem = fileSystem;
this.scrapeConfigurationService = scrapeConfigurationService;
this.scrapeLogger = GetScrapeLoggerForDisplaySync();
InitializeComponent();
Closed += (_, _) => cts?.Dispose();
Expand Down Expand Up @@ -114,6 +116,39 @@ private async void OnImportClicked(object? sender, RoutedEventArgs e)
.TapAsync(_ => scrapeLogger.Information("Import completed..."))
.EnsureAsync(() => ResetUI());

private async void OnExportScrapeConfigClicked(object? sender, RoutedEventArgs e)
=> _ = await ResetCancellationTokenSource()
.Match<CancellationToken, Exception, Result<CancellationToken, string>>(
onSuccess: DisableControlsAndClearStatus,
onFailure: ex =>
{
scrapeLogger.Error(ex, "Failed to reset cancellation token source");
UpdateStatus($"Error: {ex.Message}");
return ex.Message;
}
)
.Tap(_ => scrapeLogger.Information("Exporting scrape configuration..."))
.MapAsync(_ => scrapeConfigurationService.ExportScrapeConfigurationAsync(cts!.Token))
.Tap(importExportService.ExportScrapeConfigurationToFile)
.TapAsync(_ => scrapeLogger.Information("Scrape configuration export completed..."))
.EnsureAsync(() => ResetUI());

private async void OnImportScrapeConfigClicked(object? sender, RoutedEventArgs e)
=> _ = await ResetCancellationTokenSource()
.Match<CancellationToken, Exception, Result<CancellationToken, string>>(
onSuccess: DisableControlsAndClearStatus,
onFailure: ex =>
{
scrapeLogger.Error(ex, "Failed to reset cancellation token source");
return ex.Message;
}
)
.Tap(_ => scrapeLogger.Information("Importing scrape configuration..."))
.Bind(_ => importExportService.ImportScrapeConfigurationFromFile())
.MapAsync(entity => scrapeConfigurationService.ImportScrapeConfigurationAsync(entity, cts!.Token))
.TapAsync(_ => scrapeLogger.Information("Scrape configuration import completed..."))
.EnsureAsync(() => ResetUI());

private async void OnExportTagsClicked(object? sender, RoutedEventArgs e)
=> _ = await ResetCancellationTokenSource()
.Match<CancellationToken, Exception, Result<CancellationToken, string>>(
Expand Down Expand Up @@ -160,6 +195,8 @@ private Result<CancellationToken, string> DisableControlsAndClearStatus(Cancella
ScrapeSiteNewButton.IsEnabled = false;
ExportButton.IsEnabled = false;
ImportButton.IsEnabled = false;
ExportScrapeConfigButton.IsEnabled = false;
ImportScrapeConfigButton.IsEnabled = false;
ExportTagsButton.IsEnabled = false;
ImportTagsButton.IsEnabled = false;
CancelButton.IsEnabled = true;
Expand All @@ -182,6 +219,8 @@ private void ResetUI()
ScrapeSiteNewButton.IsEnabled = true;
ExportButton.IsEnabled = true;
ImportButton.IsEnabled = true;
ExportScrapeConfigButton.IsEnabled = true;
ImportScrapeConfigButton.IsEnabled = true;
ExportTagsButton.IsEnabled = true;
ImportTagsButton.IsEnabled = true;
CancelButton.IsEnabled = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AStar.Dev.FunctionalParadigm;
using AStar.Dev.Infrastructure.FilesDb.Models;
using FileClassificationDomain = AStar.Dev.Infrastructure.FilesDb.Models.FileClassification;
using ScrapedTagDomain = AStar.Dev.Infrastructure.FilesDb.Models.ScrapedTag;

Expand All @@ -8,6 +9,8 @@ public interface IImportExportService
{
void ExportFileClassificationsToFile(List<FileClassificationDomain> classifications);
Result<List<FileClassificationDomain>, string> ImportFileClassificationsFromFile();
void ExportScrapeConfigurationToFile(ScrapeConfigurationEntity entity);
Result<ScrapeConfigurationEntity, string> ImportScrapeConfigurationFromFile();

void ExportScrapedTagsToFile(List<ScrapedTagDomain> tags);
Result<List<ScrapedTagDomain>, string> ImportScrapedTagsFromFile();
Expand Down
Loading
Loading