diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs index 3df40a123..35ef04473 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrent.cs @@ -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 { private readonly IQBittorrentProxySelector _proxySelector; private readonly ICached _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(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; diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxySelector.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxySelector.cs index e702eef0d..d219371ee 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxySelector.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxySelector.cs @@ -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 tags, QBittorrentSettings settings); } public interface IQBittorrentProxySelector diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV1.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV1.cs index cd74c91c7..0bd5981e8 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV1.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV1.cs @@ -273,6 +273,11 @@ public void SetForceStart(string hash, bool enabled, QBittorrentSettings setting ProcessRequest(request, settings); } + public void AddTags(string hash, IEnumerable 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) diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs index 07e65acd9..4e18572fe 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentProxyV2.cs @@ -338,6 +338,15 @@ public void SetForceStart(string hash, bool enabled, QBittorrentSettings setting ProcessRequest(request, settings); } + public void AddTags(string hash, IEnumerable 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) diff --git a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs index 41cdb75bf..728011211 100644 --- a/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs +++ b/src/NzbDrone.Core/Download/Clients/QBittorrent/QBittorrentSettings.cs @@ -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)); diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index 8c6b74a1c..736579ea3 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -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",