using System.Reflection; using HtmlAgilityPack; namespace OF_DL.Services; public class FileNameService(IAuthService authService) : IFileNameService { public async Task> GetFilename(object info, object media, object author, List selectedProperties, string username, Dictionary? users = null) { Dictionary values = new(); Type type1 = info.GetType(); Type type2 = media.GetType(); PropertyInfo[] properties1 = type1.GetProperties(); PropertyInfo[] properties2 = type2.GetProperties(); foreach (string propertyName in selectedProperties) { if (propertyName.Contains("media")) { object? drmProperty = null; object? fileProperty = GetNestedPropertyValue(media, "Files"); if (fileProperty != null) { drmProperty = GetNestedPropertyValue(media, "Files.Drm"); } if (fileProperty != null && drmProperty != null && propertyName == "mediaCreatedAt") { string? mpdurl = GetNestedPropertyValue(media, "Files.Drm.Manifest.Dash") as string; string? policy = GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontPolicy") as string; string? signature = GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontSignature") as string; string? kvp = GetNestedPropertyValue(media, "Files.Drm.Signature.Dash.CloudFrontKeyPairId") as string; if (string.IsNullOrEmpty(mpdurl) || string.IsNullOrEmpty(policy) || string.IsNullOrEmpty(signature) || string.IsNullOrEmpty(kvp) || authService.CurrentAuth == null) { continue; } DateTime lastModified = await DownloadService.GetDRMVideoLastModified(string.Join(",", mpdurl, policy, signature, kvp), authService.CurrentAuth); values.Add(propertyName, lastModified.ToString("yyyy-MM-dd")); continue; } if ((fileProperty == null || drmProperty == null) && propertyName == "mediaCreatedAt") { object? source = GetNestedPropertyValue(media, "Files.Full.Url"); if (source != null) { DateTime lastModified = await DownloadService.GetMediaLastModified(source.ToString() ?? ""); values.Add(propertyName, lastModified.ToString("yyyy-MM-dd")); continue; } object? preview = GetNestedPropertyValue(media, "Preview"); if (preview != null) { DateTime lastModified = await DownloadService.GetMediaLastModified(preview.ToString() ?? ""); values.Add(propertyName, lastModified.ToString("yyyy-MM-dd")); continue; } } PropertyInfo? property = Array.Find(properties2, p => p.Name.Equals(propertyName.Replace("media", ""), StringComparison.OrdinalIgnoreCase)); if (property != null) { object? propertyValue = property.GetValue(media); if (propertyValue != null) { if (propertyValue is DateTime dateTimeValue) { values.Add(propertyName, dateTimeValue.ToString("yyyy-MM-dd")); } else { values.Add(propertyName, propertyValue.ToString() ?? ""); } } } } else if (propertyName.Contains("filename")) { object? sourcePropertyValue = GetNestedPropertyValue(media, "Files.Full.Url"); if (sourcePropertyValue != null) { Uri uri = new(sourcePropertyValue.ToString() ?? ""); string filename = Path.GetFileName(uri.LocalPath); values.Add(propertyName, filename.Split(".")[0]); } else { object? nestedPropertyValue = GetNestedPropertyValue(media, "Files.Drm.Manifest.Dash"); if (nestedPropertyValue != null) { Uri uri = new(nestedPropertyValue.ToString() ?? ""); string filename = Path.GetFileName(uri.LocalPath); values.Add(propertyName, filename.Split(".")[0] + "_source"); } } } else if (propertyName.Contains("username")) { if (!string.IsNullOrEmpty(username)) { values.Add(propertyName, username); } else { object? nestedPropertyValue = GetNestedPropertyValue(author, "Id"); if (nestedPropertyValue != null && users != null) { values.Add(propertyName, users.FirstOrDefault(u => u.Value == Convert.ToInt32(nestedPropertyValue.ToString())).Key); } } } else if (propertyName.Contains("text", StringComparison.OrdinalIgnoreCase)) { PropertyInfo? property = Array.Find(properties1, p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); if (property != null) { object? propertyValue = property.GetValue(info); if (propertyValue != null) { HtmlDocument pageDoc = new(); pageDoc.LoadHtml(propertyValue.ToString() ?? ""); string str = pageDoc.DocumentNode.InnerText; if (str.Length > 100) // TODO: add length limit to config { str = str[..100]; } values.Add(propertyName, str); } } } else { PropertyInfo? property = Array.Find(properties1, p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); if (property != null) { object? propertyValue = property.GetValue(info); if (propertyValue != null) { if (propertyValue is DateTime dateTimeValue) { values.Add(propertyName, dateTimeValue.ToString("yyyy-MM-dd")); } else { values.Add(propertyName, propertyValue.ToString() ?? ""); } } } } } return values; } public Task BuildFilename(string fileFormat, Dictionary values) { foreach (KeyValuePair kvp in values) { string placeholder = "{" + kvp.Key + "}"; fileFormat = fileFormat.Replace(placeholder, kvp.Value); } return Task.FromResult(RemoveInvalidFileNameChars($"{fileFormat}")); } private static object? GetNestedPropertyValue(object source, string propertyPath) { object? value = source; foreach (string propertyName in propertyPath.Split('.')) { PropertyInfo property = value?.GetType().GetProperty(propertyName) ?? throw new ArgumentException($"Property '{propertyName}' not found."); value = property.GetValue(value); } return value; } private static string RemoveInvalidFileNameChars(string fileName) => string.IsNullOrEmpty(fileName) ? fileName : string.Concat(fileName.Split(Path.GetInvalidFileNameChars())); }