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,100 @@
using System;
using System.IO;
using Paca.Core.Config;
using Paca.Core.Detection;
using Paca.Core.Platform;
using Paca.Core.Social;
using Paca.Core.Util;
using Xunit;
namespace Paca.Tests.Core;
public class SmartMediaNamingAndThumbnailGateTests
{
[Theory]
[InlineData("1a099dac52a596d88", true)]
[InlineData("1a0984368a2930f5", true)]
[InlineData("e3b0c44298fc1c149afbf4c8996fb924", true)]
[InlineData("550e8400-e29b-41d4-a716-446655440000", true)]
[InlineData("code-1_desktop-6d44c7cb5f84", true)]
[InlineData("my_dog_playing", false)]
[InlineData("trailer_2024_1080p", false)]
[InlineData("lecture_part1", false)]
[InlineData("video", false)]
[InlineData("cat", false)]
public void Gate_FileNameUtil_IsObfuscatedHash(string name, bool expected)
{
bool actual = FileNameUtil.IsObfuscatedHash(name);
Assert.Equal(expected, actual);
}
[Theory]
[InlineData("[유머] 오늘의 귀여운 고양이 모음 | 루리웹 유머 게시판", "[유머] 오늘의 귀여운 고양이 모음")]
[InlineData("[잡담] 질문 하나 드립니다. - 루리웹", "[잡담] 질문 하나 드립니다.")]
[InlineData("Issue #42: Bug in video player · paca/paca · GitHub", "Issue #42: Bug in video player")]
[InlineData("신규 기능 릴리즈 안내 - YouTube", "신규 기능 릴리즈 안내")]
[InlineData("PACA - Media Browser", "PACA")]
public void Gate_FileNameUtil_CleanWebTitle(string rawTitle, string expectedClean)
{
string actual = FileNameUtil.CleanWebTitle(rawTitle);
Assert.Equal(expectedClean, actual);
}
[Fact]
public void Gate_FileNameUtil_DeriveSmartTitle_PrioritizesPageTitleForObfuscatedHash()
{
var mediaUri = new Uri("https://img.ruliweb.com/2024/09/13/1a099dac52a596d88.mp4");
var pageTitle = "[유머] 오늘의 귀여운 고양이 모음 | 루리웹 유머 게시판";
// 단일 미디어
var singleTitle = FileNameUtil.DeriveSmartTitle(pageTitle, mediaUri, index: 0);
Assert.Equal("[유머] 오늘의 귀여운 고양이 모음", singleTitle);
// 복수 미디어 중 1번째, 2번째
var multi1 = FileNameUtil.DeriveSmartTitle(pageTitle, mediaUri, index: 1);
var multi2 = FileNameUtil.DeriveSmartTitle(pageTitle, mediaUri, index: 2);
Assert.Equal("[유머] 오늘의 귀여운 고양이 모음 #1", multi1);
Assert.Equal("[유머] 오늘의 귀여운 고양이 모음 #2", multi2);
}
[Fact]
public void Gate_FileNameUtil_DeriveSmartTitle_KeepsMeaningfulFileNameWhenNoPageTitle()
{
var mediaUri = new Uri("https://example.com/assets/game_trailer_final.mp4");
var title = FileNameUtil.DeriveSmartTitle(null, mediaUri, index: 0);
Assert.Equal("game_trailer_final", title);
}
[Fact]
public void Gate_DetectionContext_Supports_Thumbnail_And_Index()
{
var ctx = new DetectionContext(
Url: "https://example.com/video.mp4",
PageUrl: "https://example.com",
Kind: MediaKind.Direct,
ContentType: "video/mp4",
Title: "Test Video",
Tag: "Direct",
ThumbnailUrl: "https://example.com/poster.jpg",
MediaIndex: 2
);
Assert.Equal("https://example.com/poster.jpg", ctx.ThumbnailUrl);
Assert.Equal(2, ctx.MediaIndex);
}
[Fact]
public void Gate_MediaMuxer_ResolveFfmpeg_Discovers_ToolsDir()
{
var muxer = DesktopMediaMuxer.Default;
var config = new AppConfig(); // FfmpegPath 비워둠
var resolved = muxer.ResolveFfmpeg(config);
// 사용자 PC의 AppData/Paca/tools/ffmpeg.exe 가 존재하므로 이를 자동 발견해야 함
if (File.Exists(Path.Combine(YtDlpRunner.ToolsDir, OperatingSystem.IsWindows() ? "ffmpeg.exe" : "ffmpeg")))
{
Assert.NotNull(resolved);
Assert.True(File.Exists(resolved));
}
}
}