Baseline: WPF/Avalonia/Cli/Core + plans (BROWSER_FEATURES_PLAN v2, MOBILE_PLAN v1)
This commit is contained in:
commit
21b7c4d8bd
60 changed files with 6581 additions and 0 deletions
50
VideoDownloader.Core/Util/FileNameUtil.cs
Normal file
50
VideoDownloader.Core/Util/FileNameUtil.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System.Text;
|
||||
|
||||
namespace VideoDownloader.Core.Util;
|
||||
|
||||
public static class FileNameUtil
|
||||
{
|
||||
private static readonly char[] Invalid = Path.GetInvalidFileNameChars();
|
||||
|
||||
// 무의미한 제네릭 이름 (이름 추출 시 건너뜀)
|
||||
private static readonly HashSet<string> GenericNames = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"index", "playlist", "playlists", "master", "chunklist", "main", "play",
|
||||
"media", "video", "stream", "streaming", "vod", "output", "file", "hls",
|
||||
"dash", "manifest", "seg", "segment", "test", "default"
|
||||
};
|
||||
|
||||
/// <summary>파일명으로 사용 불가능한 문자를 '_'로 치환하고 길이를 제한한다.</summary>
|
||||
public static string Sanitize(string? name, int maxLen = 120)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) return "video";
|
||||
var extra = new[] { '"', '<', '>', '|', '*', '?' };
|
||||
var sb = new StringBuilder();
|
||||
foreach (var c in name.Trim())
|
||||
{
|
||||
if (Array.IndexOf(Invalid, c) >= 0 || Array.IndexOf(extra, c) >= 0) sb.Append('_');
|
||||
else sb.Append(c);
|
||||
}
|
||||
var result = sb.ToString().Trim().Trim('.');
|
||||
if (string.IsNullOrWhiteSpace(result)) result = "video";
|
||||
return result.Length > maxLen ? result[..maxLen].Trim() : result;
|
||||
}
|
||||
|
||||
/// <summary>미디어 URL 에서 '진짜 파일명'을 추출 (페이지 타이틀 사용 X).</summary>
|
||||
public static string DeriveName(Uri url)
|
||||
{
|
||||
var segs = url.Segments
|
||||
.Select(s => Uri.UnescapeDataString(s).Trim('/'))
|
||||
.Where(s => s.Length > 0)
|
||||
.ToArray();
|
||||
|
||||
for (int i = segs.Length - 1; i >= 0; i--)
|
||||
{
|
||||
var withoutExt = Path.GetFileNameWithoutExtension(segs[i]);
|
||||
if (string.IsNullOrWhiteSpace(withoutExt)) continue;
|
||||
if (GenericNames.Contains(withoutExt)) continue; // index.m3u8 등은 건너뜀
|
||||
return Sanitize(withoutExt);
|
||||
}
|
||||
return Sanitize(url.Host); // fallback: 호스트명
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue