mirror of https://github.com/ErsatzTV/ErsatzTV.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.9 KiB
194 lines
5.9 KiB
using System.Diagnostics.CodeAnalysis; |
|
using System.IO.Abstractions; |
|
using System.Security.Cryptography; |
|
using Bugsnag; |
|
using ErsatzTV.Core.Interfaces.Metadata; |
|
using Microsoft.Extensions.Logging; |
|
|
|
namespace ErsatzTV.Core.Metadata; |
|
|
|
public class LocalFileSystem(IFileSystem fileSystem, IClient client, ILogger<LocalFileSystem> logger) : ILocalFileSystem |
|
{ |
|
public Unit EnsureFolderExists(string folder) |
|
{ |
|
try |
|
{ |
|
if (folder != null && !fileSystem.Directory.Exists(folder)) |
|
{ |
|
fileSystem.Directory.CreateDirectory(folder); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
logger.LogWarning(ex, "Failed to ensure folder exists at {Folder}", folder); |
|
} |
|
|
|
return Unit.Default; |
|
} |
|
|
|
public DateTime GetLastWriteTime(string path) |
|
{ |
|
try |
|
{ |
|
return fileSystem.File.GetLastWriteTimeUtc(path); |
|
} |
|
catch |
|
{ |
|
return SystemTime.MinValueUtc; |
|
} |
|
} |
|
|
|
public IEnumerable<string> ListSubdirectories(string folder) |
|
{ |
|
if (fileSystem.Directory.Exists(folder)) |
|
{ |
|
try |
|
{ |
|
return fileSystem.Directory.EnumerateDirectories(folder); |
|
} |
|
catch (UnauthorizedAccessException) |
|
{ |
|
logger.LogWarning("Unauthorized access exception listing subdirectories of folder {Folder}", folder); |
|
} |
|
catch (Exception ex) |
|
{ |
|
// do nothing |
|
client.Notify(ex); |
|
} |
|
} |
|
|
|
return new List<string>(); |
|
} |
|
|
|
public IEnumerable<string> ListFiles(string folder) |
|
{ |
|
if (fileSystem.Directory.Exists(folder)) |
|
{ |
|
try |
|
{ |
|
return fileSystem.Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly) |
|
.Where(path => !Path.GetFileName(path).StartsWith("._", StringComparison.OrdinalIgnoreCase)); |
|
} |
|
catch (UnauthorizedAccessException) |
|
{ |
|
logger.LogWarning("Unauthorized access exception listing files in folder {Folder}", folder); |
|
} |
|
catch (Exception ex) |
|
{ |
|
// do nothing |
|
client.Notify(ex); |
|
} |
|
} |
|
|
|
return new List<string>(); |
|
} |
|
|
|
public IEnumerable<string> ListFiles(string folder, string searchPattern) |
|
{ |
|
if (folder is not null && fileSystem.Directory.Exists(folder)) |
|
{ |
|
try |
|
{ |
|
return fileSystem.Directory.EnumerateFiles(folder, searchPattern, SearchOption.TopDirectoryOnly) |
|
.Where(path => !Path.GetFileName(path).StartsWith("._", StringComparison.OrdinalIgnoreCase)); |
|
} |
|
catch (UnauthorizedAccessException) |
|
{ |
|
logger.LogWarning("Unauthorized access exception listing files in folder {Folder}", folder); |
|
} |
|
catch (Exception ex) |
|
{ |
|
// do nothing |
|
client.Notify(ex); |
|
} |
|
} |
|
|
|
return new List<string>(); |
|
} |
|
|
|
public IEnumerable<string> ListFiles(string folder, params string[] searchPatterns) |
|
{ |
|
if (folder is not null && fileSystem.Directory.Exists(folder)) |
|
{ |
|
try |
|
{ |
|
return searchPatterns |
|
.SelectMany(searchPattern => |
|
fileSystem.Directory.EnumerateFiles(folder, searchPattern, SearchOption.TopDirectoryOnly) |
|
.Where(path => |
|
!Path.GetFileName(path).StartsWith("._", StringComparison.OrdinalIgnoreCase))) |
|
.Distinct(); |
|
} |
|
catch (UnauthorizedAccessException) |
|
{ |
|
logger.LogWarning("Unauthorized access exception listing files in folder {Folder}", folder); |
|
} |
|
catch (Exception ex) |
|
{ |
|
// do nothing |
|
client.Notify(ex); |
|
} |
|
} |
|
|
|
return new List<string>(); |
|
} |
|
|
|
public async Task<Either<BaseError, Unit>> CopyFile(string source, string destination) |
|
{ |
|
try |
|
{ |
|
string directory = Path.GetDirectoryName(destination) ?? string.Empty; |
|
if (!fileSystem.Directory.Exists(directory)) |
|
{ |
|
fileSystem.Directory.CreateDirectory(directory); |
|
} |
|
|
|
await using FileSystemStream sourceStream = fileSystem.File.OpenRead(source); |
|
await using FileSystemStream destinationStream = fileSystem.File.Create(destination); |
|
await sourceStream.CopyToAsync(destinationStream); |
|
|
|
return Unit.Default; |
|
} |
|
catch (Exception ex) |
|
{ |
|
client.Notify(ex); |
|
return BaseError.New(ex.ToString()); |
|
} |
|
} |
|
|
|
public Unit EmptyFolder(string folder) |
|
{ |
|
try |
|
{ |
|
foreach (string file in fileSystem.Directory.GetFiles(folder)) |
|
{ |
|
fileSystem.File.Delete(file); |
|
} |
|
|
|
foreach (string directory in fileSystem.Directory.GetDirectories(folder)) |
|
{ |
|
fileSystem.Directory.Delete(directory, true); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
logger.LogWarning(ex, "Failed to empty folder at {Folder}", folder); |
|
} |
|
|
|
return Unit.Default; |
|
} |
|
|
|
[SuppressMessage("Security", "CA5351:Do Not Use Broken Cryptographic Algorithms")] |
|
public async Task<byte[]> GetHash(string path) |
|
{ |
|
using var md5 = MD5.Create(); |
|
await using var stream = fileSystem.File.OpenRead(path); |
|
return await md5.ComputeHashAsync(stream); |
|
} |
|
|
|
public string GetCustomOrDefaultFile(string folder, string file) |
|
{ |
|
string path = Path.Combine(folder, file); |
|
return fileSystem.File.Exists(path) ? path : Path.Combine(folder, $"_{file}"); |
|
} |
|
}
|
|
|