using System.Globalization;
using Microsoft.EntityFrameworkCore;
using Sakayaki.Models;
namespace Sakayaki.Services;
public sealed class SyncService(AppDbContext dbContext)
{
private static readonly string[] DefaultKeywords =
{
"ユウリ","セレナ","ヒカリ","リーリエ","ミヅキ","メイ","マリィ","ルチア","コトネ",
"大苦戦","敗北","拘束","差分","差分セット"
};
private readonly AppDbContext _dbContext = dbContext;
public async Task<int> SyncFanboxFoldersAsync(
string root,
string author,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(root))
throw new ArgumentException("Root path is required.", nameof(root));
if (string.IsNullOrWhiteSpace(author))
throw new ArgumentException("Author is required.", nameof(author));
var inserted = 0;
var pending = new List<FanboxFolder>();
foreach (var dir in Directory.GetDirectories(root))
{
cancellationToken.ThrowIfCancellationRequested();
var folderName = Path.GetFileName(dir);
if (folderName.Length < 11 || folderName[10] != '-')
continue;
var datePart = folderName.Substring(0, 10);
if (!DateTime.TryParseExact(
datePart,
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out var date))
continue;
var title = folderName.Substring(11);
var keywordsStr = BuildKeywords(title);
var fileCount = Directory.GetFiles(dir).Length;
var exists = await _dbContext.FanboxFolders.AsNoTracking().AnyAsync(
x => x.Author == author && x.Date == date && x.Title == title,
cancellationToken);
if (exists)
continue;
pending.Add(new FanboxFolder
{
FolderName = folderName,
Author = author,
Date = date,
Title = title,
Keywords = keywordsStr,
FileCount = fileCount
});
}
if (pending.Count == 0)
return 0;
_dbContext.FanboxFolders.AddRange(pending);
inserted = await _dbContext.SaveChangesAsync(cancellationToken);
return inserted;
}
private static string? BuildKeywords(string title)
{
var hit = new HashSet<string>(StringComparer.Ordinal);
var cleaned = title
.Replace("【", " ")
.Replace("】", " ")
.Replace("(", " ")
.Replace(")", " ")
.Replace("(", " ")
.Replace(")", " ")
.Replace("/", " ")
.Replace("/", " ")
.Replace(",", " ")
.Replace("_", " ")
.Replace("-", " ");
foreach (var w in cleaned.Split(' ', StringSplitOptions.RemoveEmptyEntries))
{
if (w.Length >= 2)
hit.Add(w);
}
foreach (var k in DefaultKeywords)
{
if (title.Contains(k, StringComparison.Ordinal))
hit.Add(k);
}
return hit.Count > 0 ? string.Join(",", hit) : null;
}
}