using Beam.Abstractions; using Beam.Downloaders; using Beam.Models; using Microsoft.Playwright; namespace Beam.Playwright { public class PlaywrightUnitDownloader( UnitDownloaderOptions options, PlaywrightAsyncManipulator puppetManipulator) : UnitDownloader(options) where RawType : IDocument { public PlaywrightAsyncManipulator PuppetManipulator { get; } = puppetManipulator; protected override async Task DownloadToStream(string url, int bufferSize, Stream destinationStream, IProgress progress, CancellationToken ct) { var page = await PlaywrightContext.Browser.Value.NewPageAsync(); try { await page.GotoAsync(url); await PuppetManipulator(page); var download = await page.WaitForDownloadAsync(); await using var stream = await download.CreateReadStreamAsync(); var buffer = new byte[bufferSize]; var inBuffer = 0; var downloaded = 0; while ((inBuffer = stream.Read(buffer)) > 0) { downloaded += inBuffer; progress?.Report(new DownloadReport() { BytesDownloaded = downloaded, BytesRemaining = stream.Length - downloaded }); await destinationStream.WriteAsync(buffer.AsMemory(0, inBuffer), ct); } } finally { if (!page.IsClosed) await page.CloseAsync(); } } } }