mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-19 21:46:43 -04:00
@@ -16,13 +16,19 @@ interface BlocklistDetailsModalProps {
|
|||||||
protocol: DownloadProtocol;
|
protocol: DownloadProtocol;
|
||||||
indexer?: string;
|
indexer?: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
|
source?: string;
|
||||||
onModalClose: () => void;
|
onModalClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function BlocklistDetailsModal(props: BlocklistDetailsModalProps) {
|
function BlocklistDetailsModal({
|
||||||
const { isOpen, sourceTitle, protocol, indexer, message, onModalClose } =
|
isOpen,
|
||||||
props;
|
sourceTitle,
|
||||||
|
protocol,
|
||||||
|
indexer,
|
||||||
|
message,
|
||||||
|
source,
|
||||||
|
onModalClose,
|
||||||
|
}: BlocklistDetailsModalProps) {
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onModalClose={onModalClose}>
|
<Modal isOpen={isOpen} onModalClose={onModalClose}>
|
||||||
<ModalContent onModalClose={onModalClose}>
|
<ModalContent onModalClose={onModalClose}>
|
||||||
@@ -50,6 +56,9 @@ function BlocklistDetailsModal(props: BlocklistDetailsModalProps) {
|
|||||||
data={message}
|
data={message}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
{source ? (
|
||||||
|
<DescriptionListItem title={translate('Source')} data={source} />
|
||||||
|
) : null}
|
||||||
</DescriptionList>
|
</DescriptionList>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ function BlocklistRow(props: BlocklistRowProps) {
|
|||||||
protocol,
|
protocol,
|
||||||
indexer,
|
indexer,
|
||||||
message,
|
message,
|
||||||
|
source,
|
||||||
isSelected,
|
isSelected,
|
||||||
columns,
|
columns,
|
||||||
onSelectedChange,
|
onSelectedChange,
|
||||||
@@ -154,6 +155,7 @@ function BlocklistRow(props: BlocklistRowProps) {
|
|||||||
protocol={protocol}
|
protocol={protocol}
|
||||||
indexer={indexer}
|
indexer={indexer}
|
||||||
message={message}
|
message={message}
|
||||||
|
source={source}
|
||||||
onModalClose={handleDetailsModalClose}
|
onModalClose={handleDetailsModalClose}
|
||||||
/>
|
/>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ function HistoryDetails(props: HistoryDetailsProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (eventType === 'downloadFailed') {
|
if (eventType === 'downloadFailed') {
|
||||||
const { message, indexer } = data as DownloadFailedHistory;
|
const { indexer, message, source } = data as DownloadFailedHistory;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DescriptionList>
|
<DescriptionList>
|
||||||
@@ -195,6 +195,10 @@ function HistoryDetails(props: HistoryDetailsProps) {
|
|||||||
{message ? (
|
{message ? (
|
||||||
<DescriptionListItem title={translate('Message')} data={message} />
|
<DescriptionListItem title={translate('Message')} data={message} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{source ? (
|
||||||
|
<DescriptionListItem title={translate('Source')} data={source} />
|
||||||
|
) : null}
|
||||||
</DescriptionList>
|
</DescriptionList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ function useApiMutation<T, TData>(options: MutationOptions<T, TData>) {
|
|||||||
headers: {
|
headers: {
|
||||||
...options.headers,
|
...options.headers,
|
||||||
'X-Api-Key': window.Sonarr.apiKey,
|
'X-Api-Key': window.Sonarr.apiKey,
|
||||||
|
'X-Sonarr-Client': 'Sonarr',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [options]);
|
}, [options]);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const useApiQuery = <T>(options: QueryOptions<T>) => {
|
|||||||
headers: {
|
headers: {
|
||||||
...options.headers,
|
...options.headers,
|
||||||
'X-Api-Key': window.Sonarr.apiKey,
|
'X-Api-Key': window.Sonarr.apiKey,
|
||||||
|
'X-Sonarr-Client': 'Sonarr',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ const usePagedApiQuery = <T>(options: PagedQueryOptions<T>) => {
|
|||||||
headers: {
|
headers: {
|
||||||
...options.headers,
|
...options.headers,
|
||||||
'X-Api-Key': window.Sonarr.apiKey,
|
'X-Api-Key': window.Sonarr.apiKey,
|
||||||
|
'X-Sonarr-Client': 'Sonarr',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ interface Blocklist extends ModelBase {
|
|||||||
seriesId?: number;
|
seriesId?: number;
|
||||||
indexer?: string;
|
indexer?: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
|
source?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Blocklist;
|
export default Blocklist;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export interface GrabbedHistoryData {
|
|||||||
export interface DownloadFailedHistory {
|
export interface DownloadFailedHistory {
|
||||||
message: string;
|
message: string;
|
||||||
indexer?: string;
|
indexer?: string;
|
||||||
|
source?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DownloadFolderImportedHistory {
|
export interface DownloadFolderImportedHistory {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
|
namespace NzbDrone.Common.Test.Http;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class UserAgentParserFixture : TestBase
|
||||||
|
{
|
||||||
|
// Ref *Arr `_userAgent = $"{BuildInfo.AppName}/{BuildInfo.Version} ({osName} {osVersion})";`
|
||||||
|
// Ref Mylar `Mylar3/' +str(hash) +'(' +vers +') +http://www.github.com/mylar3/mylar3/`
|
||||||
|
[TestCase("Mylar3/ 3ee23rh23irqfq (13123123) http://www.github.com/mylar3/mylar3/", "Mylar3")]
|
||||||
|
[TestCase("Lidarr/1.0.0.2300 (ubuntu 20.04)", "Lidarr")]
|
||||||
|
[TestCase("Radarr/1.0.0.2300 (ubuntu 20.04)", "Radarr")]
|
||||||
|
[TestCase("Readarr/1.0.0.2300 (ubuntu 20.04)", "Readarr")]
|
||||||
|
[TestCase("Sonarr/3.0.6.9999 (ubuntu 20.04)", "Sonarr")]
|
||||||
|
[TestCase("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", "Other")]
|
||||||
|
public void should_parse_user_agent(string userAgent, string parsedAgent)
|
||||||
|
{
|
||||||
|
UserAgentParser.ParseSource(userAgent).Should().Be(parsedAgent);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Http
|
namespace NzbDrone.Common.Http
|
||||||
{
|
{
|
||||||
public static class UserAgentParser
|
public static class UserAgentParser
|
||||||
{
|
{
|
||||||
|
private static readonly Regex AppSourceRegex = new(@"(?<agent>[a-z0-9]*)\/.*(?:\(.*\))?",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
public static string SimplifyUserAgent(string userAgent)
|
public static string SimplifyUserAgent(string userAgent)
|
||||||
{
|
{
|
||||||
if (userAgent == null || userAgent.StartsWith("Mozilla/5.0"))
|
if (userAgent == null || userAgent.StartsWith("Mozilla/5.0"))
|
||||||
@@ -11,5 +16,17 @@ namespace NzbDrone.Common.Http
|
|||||||
|
|
||||||
return userAgent;
|
return userAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ParseSource(string userAgent)
|
||||||
|
{
|
||||||
|
var match = AppSourceRegex.Match(SimplifyUserAgent(userAgent) ?? string.Empty);
|
||||||
|
|
||||||
|
if (match.Groups["agent"].Success)
|
||||||
|
{
|
||||||
|
return match.Groups["agent"].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Other";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace NzbDrone.Core.Blocklisting
|
|||||||
public IndexerFlags IndexerFlags { get; set; }
|
public IndexerFlags IndexerFlags { get; set; }
|
||||||
public ReleaseType ReleaseType { get; set; }
|
public ReleaseType ReleaseType { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
public string Source { get; set; }
|
||||||
public string TorrentInfoHash { get; set; }
|
public string TorrentInfoHash { get; set; }
|
||||||
public List<Language> Languages { get; set; }
|
public List<Language> Languages { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace NzbDrone.Core.Blocklisting
|
|||||||
bool Blocklisted(int seriesId, ReleaseInfo release);
|
bool Blocklisted(int seriesId, ReleaseInfo release);
|
||||||
bool BlocklistedTorrentHash(int seriesId, string hash);
|
bool BlocklistedTorrentHash(int seriesId, string hash);
|
||||||
PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec);
|
PagingSpec<Blocklist> Paged(PagingSpec<Blocklist> pagingSpec);
|
||||||
void Block(RemoteEpisode remoteEpisode, string message);
|
void Block(RemoteEpisode remoteEpisode, string message, string source);
|
||||||
void Delete(int id);
|
void Delete(int id);
|
||||||
void Delete(List<int> ids);
|
void Delete(List<int> ids);
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ namespace NzbDrone.Core.Blocklisting
|
|||||||
return _blocklistRepository.GetPaged(pagingSpec);
|
return _blocklistRepository.GetPaged(pagingSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Block(RemoteEpisode remoteEpisode, string message)
|
public void Block(RemoteEpisode remoteEpisode, string message, string source)
|
||||||
{
|
{
|
||||||
var blocklist = new Blocklist
|
var blocklist = new Blocklist
|
||||||
{
|
{
|
||||||
@@ -85,6 +85,7 @@ namespace NzbDrone.Core.Blocklisting
|
|||||||
Indexer = remoteEpisode.Release.Indexer,
|
Indexer = remoteEpisode.Release.Indexer,
|
||||||
Protocol = remoteEpisode.Release.DownloadProtocol,
|
Protocol = remoteEpisode.Release.DownloadProtocol,
|
||||||
Message = message,
|
Message = message,
|
||||||
|
Source = source,
|
||||||
Languages = remoteEpisode.ParsedEpisodeInfo.Languages
|
Languages = remoteEpisode.ParsedEpisodeInfo.Languages
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -185,6 +186,7 @@ namespace NzbDrone.Core.Blocklisting
|
|||||||
Indexer = message.Data.GetValueOrDefault("indexer"),
|
Indexer = message.Data.GetValueOrDefault("indexer"),
|
||||||
Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")),
|
Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")),
|
||||||
Message = message.Message,
|
Message = message.Message,
|
||||||
|
Source = message.Source,
|
||||||
Languages = message.Languages,
|
Languages = message.Languages,
|
||||||
TorrentInfoHash = message.TrackedDownload?.Protocol == DownloadProtocol.Torrent
|
TorrentInfoHash = message.TrackedDownload?.Protocol == DownloadProtocol.Torrent
|
||||||
? message.TrackedDownload.DownloadItem.DownloadId
|
? message.TrackedDownload.DownloadItem.DownloadId
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(223)]
|
||||||
|
public class add_source_to_blocklist : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("Blocklist").AddColumn("Source").AsString().Nullable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ namespace NzbDrone.Core.Download
|
|||||||
public string DownloadClient { get; set; }
|
public string DownloadClient { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
public string Source { get; set; }
|
||||||
public Dictionary<string, string> Data { get; set; }
|
public Dictionary<string, string> Data { get; set; }
|
||||||
public TrackedDownload TrackedDownload { get; set; }
|
public TrackedDownload TrackedDownload { get; set; }
|
||||||
public List<Language> Languages { get; set; }
|
public List<Language> Languages { get; set; }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Download.TrackedDownloads;
|
using NzbDrone.Core.Download.TrackedDownloads;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
@@ -11,8 +12,8 @@ namespace NzbDrone.Core.Download
|
|||||||
{
|
{
|
||||||
public interface IFailedDownloadService
|
public interface IFailedDownloadService
|
||||||
{
|
{
|
||||||
void MarkAsFailed(int historyId, bool skipRedownload = false);
|
void MarkAsFailed(int historyId, string message = null, string source = null, bool skipRedownload = false);
|
||||||
void MarkAsFailed(TrackedDownload trackedDownload, bool skipRedownload = false);
|
void MarkAsFailed(TrackedDownload trackedDownload, string message = null, string source = null, bool skipRedownload = false);
|
||||||
void Check(TrackedDownload trackedDownload);
|
void Check(TrackedDownload trackedDownload);
|
||||||
void ProcessFailed(TrackedDownload trackedDownload);
|
void ProcessFailed(TrackedDownload trackedDownload);
|
||||||
}
|
}
|
||||||
@@ -30,15 +31,16 @@ namespace NzbDrone.Core.Download
|
|||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkAsFailed(int historyId, bool skipRedownload = false)
|
public void MarkAsFailed(int historyId, string message, string source = null, bool skipRedownload = false)
|
||||||
{
|
{
|
||||||
var history = _historyService.Get(historyId);
|
message ??= "Manually marked as failed";
|
||||||
|
|
||||||
|
var history = _historyService.Get(historyId);
|
||||||
var downloadId = history.DownloadId;
|
var downloadId = history.DownloadId;
|
||||||
|
|
||||||
if (downloadId.IsNullOrWhiteSpace())
|
if (downloadId.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
PublishDownloadFailedEvent(history, new List<int> { history.EpisodeId }, "Manually marked as failed", skipRedownload: skipRedownload);
|
PublishDownloadFailedEvent(history, new List<int> { history.EpisodeId }, message, source, skipRedownload: skipRedownload);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -55,16 +57,16 @@ namespace NzbDrone.Core.Download
|
|||||||
grabbedHistory.AddRange(GetGrabbedHistory(downloadId));
|
grabbedHistory.AddRange(GetGrabbedHistory(downloadId));
|
||||||
grabbedHistory = grabbedHistory.DistinctBy(h => h.Id).ToList();
|
grabbedHistory = grabbedHistory.DistinctBy(h => h.Id).ToList();
|
||||||
|
|
||||||
PublishDownloadFailedEvent(history, GetEpisodeIds(grabbedHistory), "Manually marked as failed");
|
PublishDownloadFailedEvent(history, GetEpisodeIds(grabbedHistory), message, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MarkAsFailed(TrackedDownload trackedDownload, bool skipRedownload = false)
|
public void MarkAsFailed(TrackedDownload trackedDownload, string message, string source = null, bool skipRedownload = false)
|
||||||
{
|
{
|
||||||
var history = GetGrabbedHistory(trackedDownload.DownloadItem.DownloadId);
|
var history = GetGrabbedHistory(trackedDownload.DownloadItem.DownloadId);
|
||||||
|
|
||||||
if (history.Any())
|
if (history.Any())
|
||||||
{
|
{
|
||||||
PublishDownloadFailedEvent(history.First(), GetEpisodeIds(history), "Manually marked as failed", trackedDownload, skipRedownload: skipRedownload);
|
PublishDownloadFailedEvent(history.First(), GetEpisodeIds(history), message ?? "Manually marked as failed", source, trackedDownload, skipRedownload: skipRedownload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,10 +119,10 @@ namespace NzbDrone.Core.Download
|
|||||||
}
|
}
|
||||||
|
|
||||||
trackedDownload.State = TrackedDownloadState.Failed;
|
trackedDownload.State = TrackedDownloadState.Failed;
|
||||||
PublishDownloadFailedEvent(grabbedItems.First(), GetEpisodeIds(grabbedItems), failure, trackedDownload);
|
PublishDownloadFailedEvent(grabbedItems.First(), GetEpisodeIds(grabbedItems), failure, $"{BuildInfo.AppName} Failed Download Handling", trackedDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PublishDownloadFailedEvent(EpisodeHistory historyItem, List<int> episodeIds, string message, TrackedDownload trackedDownload = null, bool skipRedownload = false)
|
private void PublishDownloadFailedEvent(EpisodeHistory historyItem, List<int> episodeIds, string message, string source, TrackedDownload trackedDownload = null, bool skipRedownload = false)
|
||||||
{
|
{
|
||||||
Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource);
|
Enum.TryParse(historyItem.Data.GetValueOrDefault(EpisodeHistory.RELEASE_SOURCE, ReleaseSourceType.Unknown.ToString()), out ReleaseSourceType releaseSource);
|
||||||
|
|
||||||
@@ -133,6 +135,7 @@ namespace NzbDrone.Core.Download
|
|||||||
DownloadClient = historyItem.Data.GetValueOrDefault(EpisodeHistory.DOWNLOAD_CLIENT),
|
DownloadClient = historyItem.Data.GetValueOrDefault(EpisodeHistory.DOWNLOAD_CLIENT),
|
||||||
DownloadId = historyItem.DownloadId,
|
DownloadId = historyItem.DownloadId,
|
||||||
Message = message,
|
Message = message,
|
||||||
|
Source = source,
|
||||||
Data = historyItem.Data,
|
Data = historyItem.Data,
|
||||||
TrackedDownload = trackedDownload,
|
TrackedDownload = trackedDownload,
|
||||||
Languages = historyItem.Languages,
|
Languages = historyItem.Languages,
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ namespace NzbDrone.Core.History
|
|||||||
history.Data.Add("DownloadClient", message.DownloadClient);
|
history.Data.Add("DownloadClient", message.DownloadClient);
|
||||||
history.Data.Add("DownloadClientName", message.TrackedDownload?.DownloadItem.DownloadClientInfo.Name);
|
history.Data.Add("DownloadClientName", message.TrackedDownload?.DownloadItem.DownloadClientInfo.Name);
|
||||||
history.Data.Add("Message", message.Message);
|
history.Data.Add("Message", message.Message);
|
||||||
|
history.Data.Add("Source", message.Source);
|
||||||
history.Data.Add("ReleaseGroup", message.TrackedDownload?.RemoteEpisode?.ParsedEpisodeInfo?.ReleaseGroup ?? message.Data.GetValueOrDefault(EpisodeHistory.RELEASE_GROUP));
|
history.Data.Add("ReleaseGroup", message.TrackedDownload?.RemoteEpisode?.ParsedEpisodeInfo?.ReleaseGroup ?? message.Data.GetValueOrDefault(EpisodeHistory.RELEASE_GROUP));
|
||||||
history.Data.Add("Size", message.TrackedDownload?.DownloadItem.TotalSize.ToString() ?? message.Data.GetValueOrDefault(EpisodeHistory.SIZE));
|
history.Data.Add("Size", message.TrackedDownload?.DownloadItem.TotalSize.ToString() ?? message.Data.GetValueOrDefault(EpisodeHistory.SIZE));
|
||||||
history.Data.Add("Indexer", message.TrackedDownload?.RemoteEpisode?.Release?.Indexer ?? message.Data.GetValueOrDefault(EpisodeHistory.INDEXER));
|
history.Data.Add("Indexer", message.TrackedDownload?.RemoteEpisode?.Release?.Indexer ?? message.Data.GetValueOrDefault(EpisodeHistory.INDEXER));
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
{
|
{
|
||||||
if (blocklist)
|
if (blocklist)
|
||||||
{
|
{
|
||||||
_blocklistService.Block(pendingRelease.RemoteEpisode, "Pending release manually blocklisted");
|
_blocklistService.Block(pendingRelease.RemoteEpisode, "Pending release manually blocklisted", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pendingReleaseService.RemovePendingQueueItemsObsolete(pendingRelease.Id);
|
_pendingReleaseService.RemovePendingQueueItemsObsolete(pendingRelease.Id);
|
||||||
@@ -356,7 +356,7 @@ namespace Sonarr.Api.V3.Queue
|
|||||||
|
|
||||||
if (blocklist)
|
if (blocklist)
|
||||||
{
|
{
|
||||||
_failedDownloadService.MarkAsFailed(trackedDownload, skipRedownload);
|
_failedDownloadService.MarkAsFailed(trackedDownload, null, null, skipRedownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!removeFromClient && !blocklist && !changeCategory)
|
if (!removeFromClient && !blocklist && !changeCategory)
|
||||||
|
|||||||
@@ -68,13 +68,13 @@ namespace Sonarr.Api.V5.Queue
|
|||||||
}
|
}
|
||||||
|
|
||||||
[RestDeleteById]
|
[RestDeleteById]
|
||||||
public ActionResult RemoveAction(int id, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false, bool changeCategory = false)
|
public ActionResult RemoveAction(int id, string? message = null, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false, bool changeCategory = false)
|
||||||
{
|
{
|
||||||
var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id);
|
var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id);
|
||||||
|
|
||||||
if (pendingRelease != null)
|
if (pendingRelease != null)
|
||||||
{
|
{
|
||||||
Remove(pendingRelease, blocklist);
|
Remove(pendingRelease, message, blocklist);
|
||||||
|
|
||||||
return Deleted();
|
return Deleted();
|
||||||
}
|
}
|
||||||
@@ -86,14 +86,14 @@ namespace Sonarr.Api.V5.Queue
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove(trackedDownload, removeFromClient, blocklist, skipRedownload, changeCategory);
|
Remove(trackedDownload, message, removeFromClient, blocklist, skipRedownload, changeCategory);
|
||||||
_trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId);
|
_trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId);
|
||||||
|
|
||||||
return Deleted();
|
return Deleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete("bulk")]
|
[HttpDelete("bulk")]
|
||||||
public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false, [FromQuery] bool changeCategory = false)
|
public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] string? message, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false, [FromQuery] bool changeCategory = false)
|
||||||
{
|
{
|
||||||
var trackedDownloadIds = new List<string>();
|
var trackedDownloadIds = new List<string>();
|
||||||
var pendingToRemove = new List<NzbDrone.Core.Queue.Queue>();
|
var pendingToRemove = new List<NzbDrone.Core.Queue.Queue>();
|
||||||
@@ -119,12 +119,12 @@ namespace Sonarr.Api.V5.Queue
|
|||||||
|
|
||||||
foreach (var pendingRelease in pendingToRemove.DistinctBy(p => p.Id))
|
foreach (var pendingRelease in pendingToRemove.DistinctBy(p => p.Id))
|
||||||
{
|
{
|
||||||
Remove(pendingRelease, blocklist);
|
Remove(pendingRelease, message, blocklist);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var trackedDownload in trackedToRemove.DistinctBy(t => t.DownloadItem.DownloadId))
|
foreach (var trackedDownload in trackedToRemove.DistinctBy(t => t.DownloadItem.DownloadId))
|
||||||
{
|
{
|
||||||
Remove(trackedDownload, removeFromClient, blocklist, skipRedownload, changeCategory);
|
Remove(trackedDownload, message, removeFromClient, blocklist, skipRedownload, changeCategory);
|
||||||
trackedDownloadIds.Add(trackedDownload.DownloadItem.DownloadId);
|
trackedDownloadIds.Add(trackedDownload.DownloadItem.DownloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,17 +314,17 @@ namespace Sonarr.Api.V5.Queue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Remove(NzbDrone.Core.Queue.Queue pendingRelease, bool blocklist)
|
private void Remove(NzbDrone.Core.Queue.Queue pendingRelease, string? message, bool blocklist)
|
||||||
{
|
{
|
||||||
if (blocklist)
|
if (blocklist)
|
||||||
{
|
{
|
||||||
_blocklistService.Block(pendingRelease.RemoteEpisode, "Pending release manually blocklisted");
|
_blocklistService.Block(pendingRelease.RemoteEpisode, message ?? "Pending release manually blocklisted", Request.GetSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
_pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id);
|
_pendingReleaseService.RemovePendingQueueItems(pendingRelease.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TrackedDownload? Remove(TrackedDownload trackedDownload, bool removeFromClient, bool blocklist, bool skipRedownload, bool changeCategory)
|
private TrackedDownload? Remove(TrackedDownload trackedDownload, string? message, bool removeFromClient, bool blocklist, bool skipRedownload, bool changeCategory)
|
||||||
{
|
{
|
||||||
if (removeFromClient)
|
if (removeFromClient)
|
||||||
{
|
{
|
||||||
@@ -351,7 +351,7 @@ namespace Sonarr.Api.V5.Queue
|
|||||||
|
|
||||||
if (blocklist)
|
if (blocklist)
|
||||||
{
|
{
|
||||||
_failedDownloadService.MarkAsFailed(trackedDownload, skipRedownload);
|
_failedDownloadService.MarkAsFailed(trackedDownload, message, Request.GetSource(), skipRedownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!removeFromClient && !blocklist && !changeCategory)
|
if (!removeFromClient && !blocklist && !changeCategory)
|
||||||
|
|||||||
@@ -97,6 +97,16 @@ namespace Sonarr.Http.Extensions
|
|||||||
return remoteIP.ToString();
|
return remoteIP.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetSource(this HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request.Headers.TryGetValue("X-Sonarr-Client", out var source))
|
||||||
|
{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NzbDrone.Common.Http.UserAgentParser.ParseSource(request.Headers["User-Agent"]);
|
||||||
|
}
|
||||||
|
|
||||||
public static void DisableCache(this IHeaderDictionary headers)
|
public static void DisableCache(this IHeaderDictionary headers)
|
||||||
{
|
{
|
||||||
headers.Remove("Last-Modified");
|
headers.Remove("Last-Modified");
|
||||||
|
|||||||
Reference in New Issue
Block a user