New: Option to add series tags when adding torrents to qbit

Closes #7930
This commit is contained in:
Ben Martin 2025-07-08 01:34:25 +01:00 committed by GitHub
parent 010bbbd222
commit fee3f8150e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 50 additions and 2 deletions

View file

@ -14,6 +14,7 @@
using NzbDrone.Core.MediaFiles.TorrentInfo;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.RemotePathMappings;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Download.Clients.QBittorrent
@ -22,6 +23,7 @@ public class QBittorrent : TorrentClientBase<QBittorrentSettings>
{
private readonly IQBittorrentProxySelector _proxySelector;
private readonly ICached<SeedingTimeCacheEntry> _seedingTimeCache;
private readonly ITagRepository _tagRepository;
private class SeedingTimeCacheEntry
{
@ -38,12 +40,14 @@ public QBittorrent(IQBittorrentProxySelector proxySelector,
ICacheManager cacheManager,
ILocalizationService localizationService,
IBlocklistService blocklistService,
ITagRepository tagRepository,
Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, localizationService, blocklistService, logger)
{
_proxySelector = proxySelector;
_seedingTimeCache = cacheManager.GetCache<SeedingTimeCacheEntry>(GetType(), "seedingTime");
_tagRepository = tagRepository;
}
private IQBittorrentProxy Proxy => _proxySelector.GetProxy(Settings);
@ -83,7 +87,7 @@ protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string
Proxy.AddTorrentFromUrl(magnetLink, addHasSetShareLimits && setShareLimits ? remoteEpisode.SeedConfiguration : null, Settings);
if ((!addHasSetShareLimits && setShareLimits) || moveToTop || forceStart)
if ((!addHasSetShareLimits && setShareLimits) || moveToTop || forceStart || (Settings.AddSeriesTags && remoteEpisode.Series.Tags.Count > 0))
{
if (!WaitForTorrent(hash))
{
@ -125,6 +129,18 @@ protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string
_logger.Warn(ex, "Failed to set ForceStart for {0}.", hash);
}
}
if (Settings.AddSeriesTags && remoteEpisode.Series.Tags.Count > 0)
{
try
{
Proxy.AddTags(hash.ToLower(), _tagRepository.GetTags(remoteEpisode.Series.Tags).Select(tag => tag.Label), Settings);
}
catch (Exception ex)
{
_logger.Warn(ex, "Failed to add tags for {0}.", hash);
}
}
}
return hash;
@ -140,7 +156,7 @@ protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string
Proxy.AddTorrentFromFile(filename, fileContent, addHasSetShareLimits ? remoteEpisode.SeedConfiguration : null, Settings);
if ((!addHasSetShareLimits && setShareLimits) || moveToTop || forceStart)
if ((!addHasSetShareLimits && setShareLimits) || moveToTop || forceStart || (Settings.AddSeriesTags && remoteEpisode.Series.Tags.Count > 0))
{
if (!WaitForTorrent(hash))
{
@ -182,6 +198,18 @@ protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string
_logger.Warn(ex, "Failed to set ForceStart for {0}.", hash);
}
}
if (Settings.AddSeriesTags && remoteEpisode.Series.Tags.Count > 0)
{
try
{
Proxy.AddTags(hash.ToLower(), _tagRepository.GetTags(remoteEpisode.Series.Tags).Select(tag => tag.Label), Settings);
}
catch (Exception ex)
{
_logger.Warn(ex, "Failed to add tags for {0}.", hash);
}
}
}
return hash;

View file

@ -27,6 +27,7 @@ public interface IQBittorrentProxy
void SetTorrentSeedingConfiguration(string hash, TorrentSeedConfiguration seedConfiguration, QBittorrentSettings settings);
void MoveTorrentToTopInQueue(string hash, QBittorrentSettings settings);
void SetForceStart(string hash, bool enabled, QBittorrentSettings settings);
void AddTags(string hash, IEnumerable<string> tags, QBittorrentSettings settings);
}
public interface IQBittorrentProxySelector

View file

@ -273,6 +273,11 @@ public void SetForceStart(string hash, bool enabled, QBittorrentSettings setting
ProcessRequest(request, settings);
}
public void AddTags(string hash, IEnumerable<string> tags, QBittorrentSettings settings)
{
// Not supported on api v1
}
private HttpRequestBuilder BuildRequest(QBittorrentSettings settings)
{
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase)

View file

@ -338,6 +338,15 @@ public void SetForceStart(string hash, bool enabled, QBittorrentSettings setting
ProcessRequest(request, settings);
}
public void AddTags(string hash, IEnumerable<string> tags, QBittorrentSettings settings)
{
var request = BuildRequest(settings).Resource("/api/v2/torrents/addTags")
.Post()
.AddFormParameter("hashes", hash)
.AddFormParameter("tags", string.Join(",", tags));
ProcessRequest(request, settings);
}
private HttpRequestBuilder BuildRequest(QBittorrentSettings settings)
{
var requestBuilder = new HttpRequestBuilder(settings.UseSsl, settings.Host, settings.Port, settings.UrlBase)

View file

@ -73,6 +73,9 @@ public QBittorrentSettings()
[FieldDefinition(13, Label = "DownloadClientQbittorrentSettingsContentLayout", Type = FieldType.Select, SelectOptions = typeof(QBittorrentContentLayout), HelpText = "DownloadClientQbittorrentSettingsContentLayoutHelpText")]
public int ContentLayout { get; set; }
[FieldDefinition(14, Label = "DownloadClientQbittorrentSettingsAddSeriesTags", Type = FieldType.Checkbox, HelpText = "DownloadClientQbittorrentSettingsAddSeriesTagsHelpText")]
public bool AddSeriesTags { get; set; }
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

View file

@ -481,6 +481,8 @@
"DownloadClientPneumaticSettingsStrmFolder": "Strm Folder",
"DownloadClientPneumaticSettingsStrmFolderHelpText": ".strm files in this folder will be import by drone",
"DownloadClientPriorityHelpText": "Download Client Priority from 1 (Highest) to 50 (Lowest). Default: 1. Round-Robin is used for clients with the same priority.",
"DownloadClientQbittorrentSettingsAddSeriesTags": "Add Series Tags",
"DownloadClientQbittorrentSettingsAddSeriesTagsHelpText": "Add series tags to new torrents added to the download client (qBittorrent 4.1.0+)",
"DownloadClientQbittorrentSettingsContentLayout": "Content Layout",
"DownloadClientQbittorrentSettingsContentLayoutHelpText": "Whether to use qBittorrent's configured content layout, the original layout from the torrent or always create a subfolder (qBittorrent 4.3.2+)",
"DownloadClientQbittorrentSettingsFirstAndLastFirst": "First and Last First",