feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization

This commit is contained in:
Yun Chan 2026-09-14 00:39:44 +09:00
parent a88aafa1e5
commit 0e568f1f0a
975 changed files with 130593 additions and 16783 deletions

View file

@ -0,0 +1,125 @@
using System.IO;
using Paca.App.Core;
using Paca.App.ViewModels;
using Paca.Browser;
using Paca.Browser.Tabs;
using Paca.Core.Config;
using Paca.Core.Detection;
using Paca.Core.Platform;
using Paca.Core.Utils;
namespace Paca.Tests.Infrastructure;
public sealed class MockPipelineProcessRunner : IProcessRunner
{
public List<ProcessSpec> Specs { get; } = new();
public Task<ProcessResult> RunAsync(ProcessSpec spec, Action<string, string>? onLine, CancellationToken ct)
{
Specs.Add(spec);
return Task.FromResult(new ProcessResult(0, "OK", ""));
}
}
public sealed class MockPipelineCloudStorageClient : ICloudStorageClient
{
public List<string> UploadedList { get; } = new();
public Task<bool> UploadAsync(string localFilePath, string remoteDestination, Action<long, long>? onProgress, CancellationToken ct)
{
UploadedList.Add($"{localFilePath} -> {remoteDestination}");
return Task.FromResult(true);
}
public Task<bool> ExistsAsync(string remoteDestination, CancellationToken ct)
{
return Task.FromResult(UploadedList.Any(u => u.EndsWith(remoteDestination)));
}
}
/// <summary>
/// 40개 마일스톤 전 영역 통합 오케스트레이션 파이프라인 하네스.
/// </summary>
public sealed class GrandUnifiedPipeline : IDisposable
{
public string TempDir { get; }
public AppConfig Config { get; }
public TabManager TabManager { get; }
public AdBlockRuleEngine AdBlockEngine { get; }
public MemoryTurboGuard MemoryGuard { get; }
public DownloadManager DownloadManager { get; }
public VideoDeduplicator Deduplicator { get; }
public QoSTrafficShaper TrafficShaper { get; }
public ChaosMonkeyStressDefense ChaosDefense { get; }
public AudioNormalizer AudioNormalizer { get; }
public HdrToneMapper HdrToneMapper { get; }
public ChapterSplitter ChapterSplitter { get; }
public DualSubtitleEngine DualSubtitleEngine { get; }
public CloudSyncGateway CloudGateway { get; }
public MockPipelineProcessRunner ProcessRunner { get; }
public MockPipelineCloudStorageClient CloudClient { get; }
private readonly List<DownloadItemViewModel> _detectedItems = new();
private GrandUnifiedPipeline()
{
TempDir = Path.Combine(Path.GetTempPath(), "VD_Grand_" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(TempDir);
Config = new AppConfig
{
OutputFolder = Path.Combine(TempDir, "downloads")
};
Directory.CreateDirectory(Config.OutputFolder);
ProcessRunner = new MockPipelineProcessRunner();
CloudClient = new MockPipelineCloudStorageClient();
TabManager = new TabManager(() => new TabItem(), _ => { });
AdBlockEngine = new AdBlockRuleEngine();
MemoryGuard = new MemoryTurboGuard(TimeSpan.FromMinutes(10));
DownloadManager = new DownloadManager(
Config,
_ => Task.FromResult(new List<Microsoft.Web.WebView2.Core.CoreWebView2Cookie>()),
_ => { });
DownloadManager.ItemDetected += item => _detectedItems.Add(item);
Deduplicator = new VideoDeduplicator(maxHammingThreshold: 5);
TrafficShaper = new QoSTrafficShaper(maxBandwidthBytesPerSec: 10_000_000);
ChaosDefense = new ChaosMonkeyStressDefense(failureRate: 0.3);
AudioNormalizer = new AudioNormalizer(ProcessRunner);
HdrToneMapper = new HdrToneMapper(ProcessRunner);
ChapterSplitter = new ChapterSplitter(ProcessRunner);
DualSubtitleEngine = new DualSubtitleEngine();
CloudGateway = new CloudSyncGateway(CloudClient);
}
public static GrandUnifiedPipeline Create() => new();
public IReadOnlyList<DownloadItemViewModel> DetectedItems => _detectedItems;
public void SimulateWebRequest(string url, MediaKind? mediaKind = null, string? pageUrl = null)
{
var uri = new Uri(url);
// 1. 광고 차단 검사
if (AdBlockEngine.ShouldBlock(uri))
return;
// 2. 미디어 감지
if (mediaKind.HasValue)
{
DownloadManager.OnDetected(new DetectionContext(url, pageUrl ?? "https://test.local", mediaKind.Value));
}
}
public void Dispose()
{
if (Directory.Exists(TempDir))
{
try { Directory.Delete(TempDir, true); } catch { }
}
}
}