178 lines
5.1 KiB
C#
178 lines
5.1 KiB
C#
using RdtClient.Data.Enums;
|
|
using RdtClient.Data.Models.Data;
|
|
using RdtClient.Service.Helpers;
|
|
using RdtClient.Service.Services.DebridClients;
|
|
using SharpCompress.Archives;
|
|
using SharpCompress.Archives.Rar;
|
|
using SharpCompress.Archives.Zip;
|
|
using SharpCompress.Common;
|
|
|
|
namespace RdtClient.Service.Services;
|
|
|
|
public class UnpackClient(Download download, String destinationPath)
|
|
{
|
|
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
|
|
|
private readonly Torrent _torrent = download.Torrent ?? throw new($"Torrent is null");
|
|
public Boolean Finished { get; private set; }
|
|
|
|
public String? Error { get; private set; }
|
|
|
|
public Int32 Progess { get; private set; }
|
|
|
|
public void Start()
|
|
{
|
|
Progess = 0;
|
|
|
|
try
|
|
{
|
|
var filePath = DownloadHelper.GetDownloadPath(destinationPath, _torrent, download) ?? throw new("Invalid download path");
|
|
|
|
Task.Run(async delegate
|
|
{
|
|
if (!_cancellationTokenSource.IsCancellationRequested)
|
|
{
|
|
await Unpack(filePath, _cancellationTokenSource.Token);
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Error = $"An unexpected error occurred preparing download {download.Link} for torrent {_torrent.RdName}: {ex.Message}";
|
|
Finished = true;
|
|
}
|
|
}
|
|
|
|
public void Cancel()
|
|
{
|
|
_cancellationTokenSource.Cancel();
|
|
}
|
|
|
|
private async Task Unpack(String filePath, CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(filePath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var extractPath = destinationPath;
|
|
String? extractPathTemp = null;
|
|
|
|
var archiveEntries = await GetArchiveFiles(filePath);
|
|
|
|
if (!archiveEntries.Any(m => m.StartsWith(_torrent.RdName + @"\")) && !archiveEntries.Any(m => m.StartsWith(_torrent.RdName + "/")))
|
|
{
|
|
extractPath = Path.Combine(destinationPath, _torrent.RdName!);
|
|
}
|
|
|
|
if (archiveEntries.Any(m => m.Contains(".r00")))
|
|
{
|
|
extractPathTemp = Path.Combine(extractPath, Guid.NewGuid().ToString());
|
|
|
|
if (!Directory.Exists(extractPathTemp))
|
|
{
|
|
Directory.CreateDirectory(extractPathTemp);
|
|
}
|
|
}
|
|
|
|
if (extractPathTemp != null)
|
|
{
|
|
Extract(filePath, extractPathTemp, cancellationToken);
|
|
|
|
await FileHelper.Delete(filePath);
|
|
|
|
var rarFiles = Directory.GetFiles(extractPathTemp, "*.r00", SearchOption.TopDirectoryOnly);
|
|
|
|
foreach (var rarFile in rarFiles)
|
|
{
|
|
var mainRarFile = Path.ChangeExtension(rarFile, ".rar");
|
|
|
|
if (File.Exists(mainRarFile))
|
|
{
|
|
Extract(mainRarFile, extractPath, cancellationToken);
|
|
}
|
|
|
|
await FileHelper.DeleteDirectory(extractPathTemp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Extract(filePath, extractPath, cancellationToken);
|
|
|
|
await FileHelper.Delete(filePath);
|
|
}
|
|
|
|
if (_torrent.ClientKind == Provider.TorBox)
|
|
{
|
|
TorBoxDebridClient.MoveHashDirContents(extractPath, _torrent);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Error = $"An unexpected error occurred unpacking {download.Link} for torrent {_torrent.RdName}: {ex.Message}";
|
|
}
|
|
finally
|
|
{
|
|
Finished = true;
|
|
}
|
|
}
|
|
|
|
private static async Task<IList<String>> GetArchiveFiles(String filePath)
|
|
{
|
|
await using Stream stream = File.OpenRead(filePath);
|
|
|
|
var extension = Path.GetExtension(filePath);
|
|
|
|
IArchive archive;
|
|
|
|
if (extension == ".zip")
|
|
{
|
|
archive = ZipArchive.OpenArchive(stream);
|
|
}
|
|
else
|
|
{
|
|
archive = RarArchive.OpenArchive(stream);
|
|
}
|
|
|
|
var entries = archive.Entries
|
|
.Where(entry => !entry.IsDirectory)
|
|
.Select(m => m.Key!)
|
|
.ToList();
|
|
|
|
archive.Dispose();
|
|
|
|
return entries;
|
|
}
|
|
|
|
private void Extract(String filePath, String extractPath, CancellationToken cancellationToken)
|
|
{
|
|
var parts = ArchiveFactory.GetFileParts(filePath);
|
|
|
|
var fi = parts.Select(m => new FileInfo(m));
|
|
|
|
var extension = Path.GetExtension(filePath);
|
|
|
|
IArchive archive;
|
|
|
|
if (extension == ".zip")
|
|
{
|
|
archive = ZipArchive.OpenArchive(fi);
|
|
}
|
|
else
|
|
{
|
|
archive = RarArchive.OpenArchive(fi);
|
|
}
|
|
|
|
archive.WriteToDirectory(extractPath,
|
|
new Progress<ProgressReport>(d =>
|
|
{
|
|
Progess = (Int32)Math.Round(d.PercentComplete ?? 0);
|
|
}));
|
|
|
|
archive.Dispose();
|
|
|
|
GC.Collect();
|
|
}
|
|
}
|