mirror of
https://github.com/Cleanuparr/Cleanuparr.git
synced 2026-03-26 01:52:41 -04:00
139 lines
5.4 KiB
C#
139 lines
5.4 KiB
C#
using Cleanuparr.Domain.Entities;
|
|
using Cleanuparr.Infrastructure.Extensions;
|
|
using Cleanuparr.Infrastructure.Features.Context;
|
|
using Cleanuparr.Persistence.Models.Configuration.DownloadCleaner;
|
|
using Microsoft.Extensions.Logging;
|
|
using Transmission.API.RPC.Entity;
|
|
|
|
namespace Cleanuparr.Infrastructure.Features.DownloadClient.Transmission;
|
|
|
|
public partial class TransmissionService
|
|
{
|
|
public override async Task<List<ITorrentItemWrapper>> GetSeedingDownloads()
|
|
{
|
|
var result = await _client.TorrentGetAsync(Fields);
|
|
return result?.Torrents
|
|
?.Where(x => !string.IsNullOrEmpty(x.HashString))
|
|
.Where(x => x.Status is 5 or 6)
|
|
.Select(ITorrentItemWrapper (x) => new TransmissionItemWrapper(x))
|
|
.ToList() ?? [];
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override List<ITorrentItemWrapper>? FilterDownloadsToBeCleanedAsync(List<ITorrentItemWrapper>? downloads, List<SeedingRule> seedingRules)
|
|
{
|
|
return downloads
|
|
?.Where(x => seedingRules
|
|
.Any(cat => cat.Name.Equals(x.Category, StringComparison.InvariantCultureIgnoreCase))
|
|
)
|
|
.ToList();
|
|
}
|
|
|
|
public override List<ITorrentItemWrapper>? FilterDownloadsToChangeCategoryAsync(List<ITorrentItemWrapper>? downloads, List<string> categories)
|
|
{
|
|
return downloads
|
|
?.Where(x => !string.IsNullOrEmpty(x.Hash))
|
|
.Where(x => categories.Any(cat => cat.Equals(x.Category, StringComparison.InvariantCultureIgnoreCase)))
|
|
.ToList();
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public override async Task DeleteDownload(ITorrentItemWrapper torrent, bool deleteSourceFiles)
|
|
{
|
|
var transmissionTorrent = (TransmissionItemWrapper)torrent;
|
|
await _client.TorrentRemoveAsync([transmissionTorrent.Info.Id], deleteSourceFiles);
|
|
}
|
|
|
|
public override async Task CreateCategoryAsync(string name)
|
|
{
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
public override async Task ChangeCategoryForNoHardLinksAsync(List<ITorrentItemWrapper>? downloads)
|
|
{
|
|
if (downloads?.Count is null or 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var downloadCleanerConfig = ContextProvider.Get<DownloadCleanerConfig>(nameof(DownloadCleanerConfig));
|
|
|
|
foreach (TransmissionItemWrapper torrent in downloads.Cast<TransmissionItemWrapper>())
|
|
{
|
|
if (string.IsNullOrEmpty(torrent.Hash) || string.IsNullOrEmpty(torrent.Name) || string.IsNullOrEmpty(torrent.Info.DownloadDir))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
ContextProvider.Set(ContextProvider.Keys.ItemName, torrent.Name);
|
|
ContextProvider.Set(ContextProvider.Keys.Hash, torrent.Hash);
|
|
ContextProvider.Set(ContextProvider.Keys.DownloadClientUrl, _downloadClientConfig.ExternalOrInternalUrl);
|
|
ContextProvider.Set(ContextProvider.Keys.DownloadClientType, _downloadClientConfig.TypeName);
|
|
ContextProvider.Set(ContextProvider.Keys.DownloadClientName, _downloadClientConfig.Name);
|
|
|
|
if (torrent.Info.Files is null || torrent.Info.FileStats is null)
|
|
{
|
|
_logger.LogDebug("skip | download has no files | {name}", torrent.Name);
|
|
continue;
|
|
}
|
|
|
|
bool hasHardlinks = false;
|
|
bool hasErrors = false;
|
|
|
|
for (int i = 0; i < torrent.Info.Files.Length; i++)
|
|
{
|
|
TransmissionTorrentFiles file = torrent.Info.Files[i];
|
|
TransmissionTorrentFileStats stats = torrent.Info.FileStats[i];
|
|
|
|
if (stats.Wanted is null or false || string.IsNullOrEmpty(file.Name))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string filePath = string.Join(Path.DirectorySeparatorChar, Path.Combine(torrent.Info.DownloadDir, file.Name).Split(['\\', '/']));
|
|
|
|
long hardlinkCount = _hardLinkFileService.GetHardLinkCount(filePath, downloadCleanerConfig.UnlinkedIgnoredRootDirs.Count > 0);
|
|
|
|
if (hardlinkCount < 0)
|
|
{
|
|
_logger.LogError("skip | file does not exist or insufficient permissions | {file}", filePath);
|
|
hasErrors = true;
|
|
break;
|
|
}
|
|
|
|
if (hardlinkCount > 0)
|
|
{
|
|
hasHardlinks = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hasErrors)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (hasHardlinks)
|
|
{
|
|
_logger.LogDebug("skip | download has hardlinks | {name}", torrent.Name);
|
|
continue;
|
|
}
|
|
|
|
string currentCategory = torrent.Category ?? string.Empty;
|
|
string newLocation = torrent.Info.GetNewLocationByAppend(downloadCleanerConfig.UnlinkedTargetCategory);
|
|
|
|
await _dryRunInterceptor.InterceptAsync(ChangeDownloadLocation, torrent.Info.Id, newLocation);
|
|
|
|
_logger.LogInformation("category changed for {name}", torrent.Name);
|
|
|
|
await _eventPublisher.PublishCategoryChanged(currentCategory, downloadCleanerConfig.UnlinkedTargetCategory);
|
|
|
|
torrent.Category = downloadCleanerConfig.UnlinkedTargetCategory;
|
|
}
|
|
}
|
|
|
|
protected virtual async Task ChangeDownloadLocation(long downloadId, string newLocation)
|
|
{
|
|
await _client.TorrentSetLocationAsync([downloadId], newLocation, true);
|
|
}
|
|
} |