using System.Globalization; using System.IO; namespace EmbyToolbox.Services; /// Единый каталог extract\audio|subtitles|attachments и имена без молчаливого перезаписывания. public static class TrackExtractOutputPaths { /// Абсолютный путь к каталогу …\extract или null. public static string? TryPrepareExtractDirectories(string destinationRootFolder) { if (string.IsNullOrWhiteSpace(destinationRootFolder)) { return null; } try { var root = Path.GetFullPath(destinationRootFolder.Trim()); var extractRoot = Path.Combine(root, "extract"); Directory.CreateDirectory(Path.Combine(extractRoot, "audio")); Directory.CreateDirectory(Path.Combine(extractRoot, "subtitles")); Directory.CreateDirectory(Path.Combine(extractRoot, "attachments")); return extractRoot; } catch (ArgumentException) { return null; } catch (IOException) { return null; } catch (UnauthorizedAccessException) { return null; } } /// Если в уже есть файл с таким именем — добавляет _1, _2… перед расширением. public static string AllocateUniqueFilename(string parentDirectory, string desiredFileNameOnly) { var safe = Path.GetFileName(desiredFileNameOnly); if (string.IsNullOrEmpty(safe)) { safe = "output.bin"; } if (!Exists(parentDirectory, safe)) { return safe; } var stem = Path.GetFileNameWithoutExtension(safe); var ext = Path.GetExtension(safe); if (string.IsNullOrEmpty(stem)) { stem = "file"; } for (var i = 1; i < 10_000; i++) { var candidate = $"{stem}_{i.ToString(CultureInfo.InvariantCulture)}{ext}"; if (!Exists(parentDirectory, candidate)) { return candidate; } } return $"{stem}_{Guid.NewGuid():N}{ext}"; } private static bool Exists(string parentDirectory, string fileNameOnly) => File.Exists(Path.Combine(parentDirectory, fileNameOnly)); }