50 lines
2 KiB
C#
50 lines
2 KiB
C#
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: 호스트명
|
|
}
|
|
}
|