New: (Clients) Torrent and Usenet Blackhole

Fixes #238
pull/387/head
Qstick 3 years ago
parent 13b458090d
commit b3f8e648cd

@ -194,5 +194,21 @@ namespace NzbDrone.Common.Extensions
var inputBytes = encoding.GetBytes(searchString); var inputBytes = encoding.GetBytes(searchString);
return encoding.GetString(WebUtility.UrlDecodeToBytes(inputBytes, 0, inputBytes.Length)); return encoding.GetString(WebUtility.UrlDecodeToBytes(inputBytes, 0, inputBytes.Length));
} }
public static string CleanFileName(this string name)
{
string result = name;
string[] badCharacters = { "\\", "/", "<", ">", "?", "*", ":", "|", "\"" };
string[] goodCharacters = { "+", "+", "", "", "!", "-", "-", "", "" };
result = result.Replace(": ", " - ");
for (int i = 0; i < badCharacters.Length; i++)
{
result = result.Replace(badCharacters[i], goodCharacters[i]);
}
return result.TrimStart(' ', '.').TrimEnd(' ');
}
} }
} }

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download.Clients.Blackhole
{
public class TorrentBlackhole : TorrentClientBase<TorrentBlackholeSettings>
{
public override bool PreferTorrentFile => true;
public TorrentBlackhole(ITorrentFileInfoReader torrentFileInfoReader,
IHttpClient httpClient,
IConfigService configService,
IDiskProvider diskProvider,
Logger logger)
: base(torrentFileInfoReader, httpClient, configService, diskProvider, logger)
{
}
protected override string AddFromTorrentLink(ReleaseInfo release, string hash, string torrentLink)
{
throw new NotImplementedException("Blackhole does not support redirected indexers.");
}
protected override string AddFromMagnetLink(ReleaseInfo release, string hash, string magnetLink)
{
if (!Settings.SaveMagnetFiles)
{
throw new NotSupportedException("Blackhole does not support magnet links.");
}
var title = release.Title;
title = title.CleanFileName();
var filepath = Path.Combine(Settings.TorrentFolder, $"{title}.{Settings.MagnetFileExtension.Trim('.')}");
var fileContent = Encoding.UTF8.GetBytes(magnetLink);
using (var stream = _diskProvider.OpenWriteStream(filepath))
{
stream.Write(fileContent, 0, fileContent.Length);
}
_logger.Debug("Saving magnet link succeeded, saved to: {0}", filepath);
return null;
}
protected override string AddFromTorrentFile(ReleaseInfo release, string hash, string filename, byte[] fileContent)
{
var title = release.Title;
title = title.CleanFileName();
var filepath = Path.Combine(Settings.TorrentFolder, string.Format("{0}.torrent", title));
using (var stream = _diskProvider.OpenWriteStream(filepath))
{
stream.Write(fileContent, 0, fileContent.Length);
}
_logger.Debug("Torrent Download succeeded, saved to: {0}", filepath);
return null;
}
public override string Name => "Torrent Blackhole";
protected override void Test(List<ValidationFailure> failures)
{
failures.AddIfNotNull(TestFolder(Settings.TorrentFolder, "TorrentFolder"));
}
}
}

@ -0,0 +1,46 @@
using System.ComponentModel;
using FluentValidation;
using Newtonsoft.Json;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Core.Download.Clients.Blackhole
{
public class TorrentBlackholeSettingsValidator : AbstractValidator<TorrentBlackholeSettings>
{
public TorrentBlackholeSettingsValidator()
{
//Todo: Validate that the path actually exists
RuleFor(c => c.TorrentFolder).IsValidPath();
RuleFor(c => c.MagnetFileExtension).NotEmpty();
}
}
public class TorrentBlackholeSettings : IProviderConfig
{
public TorrentBlackholeSettings()
{
MagnetFileExtension = ".magnet";
}
private static readonly TorrentBlackholeSettingsValidator Validator = new TorrentBlackholeSettingsValidator();
[FieldDefinition(0, Label = "Torrent Folder", Type = FieldType.Path, HelpText = "Folder in which Prowlarr will store the .torrent file")]
public string TorrentFolder { get; set; }
[DefaultValue(false)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[FieldDefinition(1, Label = "Save Magnet Files", Type = FieldType.Checkbox, HelpText = "Save a .magnet file with the magnet link if no .torrent file is available (only useful if the download client supports .magnet files)")]
public bool SaveMagnetFiles { get; set; }
[FieldDefinition(2, Label = "Save Magnet Files", Type = FieldType.Textbox, HelpText = "Extension to use for magnet links, defaults to '.magnet'")]
public string MagnetFileExtension { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.IO;
using FluentValidation.Results;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Download.Clients.Blackhole
{
public class UsenetBlackhole : UsenetClientBase<UsenetBlackholeSettings>
{
public UsenetBlackhole(IHttpClient httpClient,
IConfigService configService,
IDiskProvider diskProvider,
Logger logger)
: base(httpClient, configService, diskProvider, logger)
{
}
protected override string AddFromLink(ReleaseInfo release)
{
throw new NotSupportedException("Blackhole does not support redirected indexers.");
}
protected override string AddFromNzbFile(ReleaseInfo release, string filename, byte[] fileContent)
{
var title = release.Title;
title = title.CleanFileName();
var filepath = Path.Combine(Settings.NzbFolder, title + ".nzb");
using (var stream = _diskProvider.OpenWriteStream(filepath))
{
stream.Write(fileContent, 0, fileContent.Length);
}
_logger.Debug("NZB Download succeeded, saved to: {0}", filepath);
return null;
}
public override string Name => "Usenet Blackhole";
protected override void Test(List<ValidationFailure> failures)
{
failures.AddIfNotNull(TestFolder(Settings.NzbFolder, "NzbFolder"));
}
}
}

@ -0,0 +1,29 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Core.Download.Clients.Blackhole
{
public class UsenetBlackholeSettingsValidator : AbstractValidator<UsenetBlackholeSettings>
{
public UsenetBlackholeSettingsValidator()
{
RuleFor(c => c.NzbFolder).IsValidPath();
}
}
public class UsenetBlackholeSettings : IProviderConfig
{
private static readonly UsenetBlackholeSettingsValidator Validator = new UsenetBlackholeSettingsValidator();
[FieldDefinition(0, Label = "Nzb Folder", Type = FieldType.Path, HelpText = "Folder in which Prowlarr will store the .nzb file")]
public string NzbFolder { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}
Loading…
Cancel
Save