using JSMR.Application.Integrations.Chobit.Models; using JSMR.Application.Integrations.Chobit.Ports; using JSMR.Application.Integrations.DLSite.Models; using JSMR.Application.Integrations.DLSite.Models.ReleasedWorks; using JSMR.Application.Integrations.DLSite.Ports; using JSMR.Application.Scanning.Contracts; using JSMR.Application.Scanning.Ports; using JSMR.Domain.Enums; using JSMR.Infrastructure.Common.Languages; namespace JSMR.Infrastructure.Scanning; public class VoiceWorkIngestBuilder( IDLSiteClient dlsiteClient, IChobitClient chobitClient, IReleasedWorksProvider releasedWorksProvider, ILanguageIdentifier languageIdentifier) : IVoiceWorkIngestBuilder { public async Task BuildAsync(VoiceWorkScanResult scanResult, CancellationToken cancellationToken) { string[] productIds = [.. scanResult.Works.Where(x => !string.IsNullOrWhiteSpace(x.ProductId)).Select(x => x.ProductId!)]; Task detailsTask = dlsiteClient.GetVoiceWorkDetailsAsync(productIds, cancellationToken); Task chobitTask = chobitClient.GetSampleInfoAsync(productIds, cancellationToken); Task releasedTask = releasedWorksProvider.GetReleasedWorksAsync(scanResult, cancellationToken); await Task.WhenAll(detailsTask, chobitTask, releasedTask); VoiceWorkDetailCollection voiceWorkDetails = await detailsTask; ChobitResultCollection chobitResults = await chobitTask; ReleasedWorksCollection releasedWorkCollection = await releasedTask; List ingests = []; foreach (DLSiteWork work in scanResult.Works) { voiceWorkDetails.TryGetValue(work.ProductId!, out VoiceWorkDetails? details); chobitResults.TryGetValue(work.ProductId, out ChobitResult? chobit); releasedWorkCollection.TryGetValue(work.ProductId, out ReleasedWork? releasedWork); VoiceWorkIngest ingest = new() { MakerId = work.MakerId, MakerName = work.Maker, ProductId = work.ProductId, Title = details?.Title ?? work.ProductName, Description = work.Description ?? string.Empty, Tags = work.Tags, Creators = work.Creators, WishlistCount = details?.WishlistCount ?? 0, Downloads = Math.Max(work.Downloads, details?.DownloadCount ?? 0), HasTrial = work.HasTrial || (details?.HasTrial ?? false), HasChobit = chobit?.Count > 0, StarRating = work.StarRating, Votes = work.Votes, AgeRating = details?.AgeRating ?? work.AgeRating, HasImage = !string.IsNullOrEmpty(work.ImageUrl) && !work.ImageUrl.Contains("no_img", StringComparison.OrdinalIgnoreCase), SupportedLanguages = details?.SupportedLanguages ?? [], ExpectedDate = work.ExpectedDate, SalesDate = work.SalesDate, RegistrationDate = details?.RegistrationDate, AI = details?.AI ?? AIGeneration.None, Series = details?.Series, Translation = details?.Translation, Localizations = GetLocalizationIngests(releasedWork) }; ingests.Add(ingest); } return [.. ingests]; } private VoiceWorkLocalizationIngest[] GetLocalizationIngests(ReleasedWork? releasedWork) { if (releasedWork is null) return []; Language titleLanguage = languageIdentifier.GetLanguage(releasedWork.Title); Language descriptionLanguage = languageIdentifier.GetLanguage(releasedWork.Description); if (titleLanguage is not Language.English && descriptionLanguage is not Language.English) return []; VoiceWorkLocalizationIngest localizationIngest = new() { Title = releasedWork.Title, Description = releasedWork.Description, Language = Language.English }; return [localizationIngest]; } }