1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-23 17:14:46 -04:00

Compare commits

..

56 Commits

Author SHA1 Message Date
Devin Buhl
98856e6747 Merge pull request #263 from Radarr/patch/update-movie-list
Add in theaters to 1st coumn in movie list
2017-01-14 16:51:27 -05:00
Devin Buhl
8fb5049899 Add in theaters to 1st coumn in movie list 2017-01-14 16:43:51 -05:00
Devin Buhl
3f62911a4f Merge pull request #260 from Radarr/patch/fix-downloadservice
Simplify completed download service
2017-01-14 14:12:54 -05:00
Devin Buhl
170349c950 Update CompletedDownloadService.cs 2017-01-14 14:07:34 -05:00
Devin Buhl
6c413d83eb Simply completed download service 2017-01-14 14:02:45 -05:00
Leonardo Galli
3afd27cad3 Merge branch 'develop' of https://github.com/Radarr/Radarr into develop 2017-01-14 19:21:52 +01:00
Leonardo Galli
149faf467d Fixed exception when Quality meets cutoff. 2017-01-14 19:21:48 +01:00
Devin Buhl
ce52bb8f68 Merge pull request #258 from Radarr/patch/fix-title-slugs-again
Fixed TitleSlug For Realz!
2017-01-14 13:18:58 -05:00
Devin Buhl
4bb5857444 Fixed TitleSlug For Realz! 2017-01-14 13:14:42 -05:00
Devin Buhl
620f09ef8b Merge pull request #257 from Radarr/patch-torpotato-regression
Torpotato username regression
2017-01-14 12:31:16 -05:00
Devin Buhl
16c1a2ee50 Torpotato username regression 2017-01-14 12:27:16 -05:00
Leonardo Galli
4b559cf29c Fix history items getting deleted because they do not have a series id. 2017-01-14 14:23:48 +01:00
Leonardo Galli
ca03f21b03 If this does not fix stuff with no history, I have no clue anymore. 2017-01-14 13:56:42 +01:00
Leonardo Galli
f481fe9ea9 Added more checks when tracking downloads. It should work now, even if history was not present. 2017-01-14 13:36:14 +01:00
Leonardo Galli
3a0278d0a1 Use MediaInfo to correctly identify quality when scanning disk as some file names may not contain the real quality.
Fixes #170
2017-01-14 13:33:30 +01:00
Leonardo Galli
d18b15d504 Should help identify problem with queue trying to reimport stuff. 2017-01-14 13:00:10 +01:00
Leonardo Galli
dc7e75187c Should fix issue when history fails to capture a download item. 2017-01-14 12:47:45 +01:00
Mitchell Cash
68a0ef65df Use DOGnzb name as the default rather than the URL (#250) 2017-01-14 12:15:59 +01:00
Leonardo Galli
fe11928487 Disable migration 117, takes too long to complete 2017-01-14 11:56:08 +01:00
Leonardo Galli
41dda3af48 Update uTorrent to be able to use it as download client. 2017-01-14 11:50:18 +01:00
Leonardo Galli
8c3260c545 Remove file count, unecessary after the file info tab was added
Fixes #215.
2017-01-14 11:41:39 +01:00
Leonardo Galli
bd0ec5dfce Fix epic fail on migration 117 2017-01-14 10:13:31 +01:00
Devin Buhl
ad38437b70 Merge pull request #248 from mitchellcash/sabnzbd_develop
Fixed: Parsing of SABnzbd develop version
2017-01-14 00:57:04 -05:00
Mark McDowall
4447b7cd62 Fixed: Parsing of SABnzbd develop version 2017-01-14 15:16:19 +10:00
Devin Buhl
d33de0d158 Merge pull request #247 from Radarr/patch/awesomehd-rsssync
Add rss sync to awesome-hd
2017-01-13 22:00:00 -05:00
Devin Buhl
dd5049b483 Add rss sync to awesome-hd 2017-01-13 21:55:07 -05:00
Leonardo Galli
29586667cb Files tab is now present. (#245)
* Adding file info tab. Not finished yet.

* Adding more media info options.

* Deleting files now works. Fixes #127

* Fix button for modifying episode files.

* Get Media Info when running DiskScanService.
2017-01-13 19:03:37 -05:00
Devin Buhl
5daece0ed4 Merge pull request #244 from Radarr/revert-238-patch/fix-slugs
Revert "Fix movie title slugs"
2017-01-13 18:24:23 -05:00
Devin Buhl
5dc63e5607 Revert "Fix movie title slugs" 2017-01-13 18:20:22 -05:00
Devin Buhl
7df283e57f Merge pull request #238 from Radarr/patch/fix-slugs
Fix movie title slugs
2017-01-13 18:07:13 -05:00
Devin Buhl
e9b6c250f7 Revert TMDBResources 2017-01-13 17:56:34 -05:00
Devin Buhl
10515156d1 Merge pull request #243 from Radarr/patch/update-torznab
Update Torznab to work with movies
2017-01-13 17:51:35 -05:00
Devin Buhl
4260b58535 Update Torznab to work with movies 2017-01-13 17:34:27 -05:00
Devin Buhl
3a386f2e18 Merge pull request #241 from Radarr/patch/fix-torpotato-age
#236 #239 - Fixed user being needed & fixed age on torrentpotato
2017-01-13 16:33:01 -05:00
Devin Buhl
d3bd0c9b69 This conditional makes more sense. 2017-01-13 16:16:31 -05:00
Devin Buhl
3180e648b4 #236 #239 - Fixed user being needed, fixed age on torrentpotato 2017-01-13 16:12:49 -05:00
Devin Buhl
d0c93759c6 Fix Movie Title Slugs #233 2017-01-13 15:49:57 -05:00
William Comartin
f7471940c4 Add Missing Filter (#237) 2017-01-13 20:57:25 +01:00
Devin Buhl
3a6873cc4d Merge pull request #232 from Radarr/patch/awesomehd
awesomeHD indexer support - Clean up Deluge, Transmission, rTorrent, QBitTorrent - Fix Sorting Titles
2017-01-13 13:15:52 -05:00
Leonardo Galli
330ae38ec2 Merge branch 'develop' of https://github.com/Radarr/Radarr into develop 2017-01-13 19:03:03 +01:00
Leonardo Galli
a0ecb19e32 DownloadMonitoringService should now not care about deleted movies. Fixes #131. 2017-01-13 19:02:59 +01:00
Leonardo Galli
38c966c07b Queue Service should now work properly again.
Fixes issue with Activity Tab
2017-01-13 18:57:43 +01:00
Devin Buhl
ad824d4da5 Finally fix for sorting title (hopefully) 2017-01-13 12:16:12 -05:00
Leonardo Galli
e76c160afe Downloaded column should now use the correct quality name. Fixes #210. 2017-01-13 18:13:39 +01:00
Devin Buhl
6a62546a4d Clean up QBitTorrent 2017-01-13 11:25:59 -05:00
Devin Buhl
0efdc78f8d Clean up rTorrent 2017-01-13 11:21:34 -05:00
Devin Buhl
fdd06127fc Clean up Transmission 2017-01-13 11:13:41 -05:00
Devin Buhl
317f8917b9 Clean up Deluge Settings 2017-01-13 11:08:36 -05:00
vertigo235
4038ce18c3 update movie monitor tooltip (#223) 2017-01-13 16:08:24 +01:00
Mike
7f3ca85953 Stop incrementing version for pull requests. 2017-01-13 06:15:38 +01:00
Devin Buhl
b93a9719fe initial awesomeHD support 2017-01-12 23:06:26 -05:00
Devin Buhl
2ef18edf08 Merge pull request #217 from aaearon/indexer-fix/omgwtfnzbs
omgwtfnzbs: fixed parsing of GetInfoUrl and updated tests
2017-01-12 23:00:30 -05:00
Tim Schindler
d61b9ab207 omgwtfnzbs: fixed parsing of GetInfoUrl and updated tests 2017-01-12 21:02:27 -05:00
Devin Buhl
abf4b137f1 Merge pull request #208 from Radarr/patch/usenet-crawler
improved categories, added Nzb-Tortuga as a preset
2017-01-12 18:51:52 -05:00
Devin Buhl
774c85f06b improved categories, added Nzb-Tortuga as a preset 2017-01-12 18:44:05 -05:00
Leonardo Galli
a060335bbc Update readme.md 2017-01-13 00:15:27 +01:00
73 changed files with 2207 additions and 1514 deletions

View File

@@ -36,6 +36,9 @@ artifacts:
cache:
- '%USERPROFILE%\.nuget\packages'
- node_modules
pull_requests:
do_not_increment_build_number: true
only_commits:
files:

View File

@@ -26,6 +26,8 @@ This fork of Sonarr aims to turn it into something like Couchpotato.
## Download
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
To connect to the UI, fire up your browser and open localhost:7878 or your-ip:7878.
Docker containers from [linuxserver.io](https://linuxserver.io) can be found here.
* [Radarr (x64)](https://hub.docker.com/r/linuxserver/radarr/)
* [Radarr (armhf)](https://hub.docker.com/r/lsioarmhf/radarr/)

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.IO;
using NLog;
using NzbDrone.Api.REST;
using NzbDrone.Api.Movie;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Tv;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.SignalR;
namespace NzbDrone.Api.EpisodeFiles
{
public class MovieFileModule : NzbDroneRestModuleWithSignalR<MovieFileResource, MovieFile>
//IHandle<EpisodeFileAddedEvent>
{
private readonly IMediaFileService _mediaFileService;
private readonly IRecycleBinProvider _recycleBinProvider;
private readonly IMovieService _seriesService;
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
private readonly Logger _logger;
public MovieFileModule(IBroadcastSignalRMessage signalRBroadcaster,
IMediaFileService mediaFileService,
IRecycleBinProvider recycleBinProvider,
IMovieService seriesService,
IQualityUpgradableSpecification qualityUpgradableSpecification,
Logger logger)
: base(signalRBroadcaster)
{
_mediaFileService = mediaFileService;
_recycleBinProvider = recycleBinProvider;
_seriesService = seriesService;
_qualityUpgradableSpecification = qualityUpgradableSpecification;
_logger = logger;
/*GetResourceById = GetEpisodeFile;
GetResourceAll = GetEpisodeFiles;
UpdateResource = SetQuality;*/
DeleteResource = DeleteEpisodeFile;
}
/*private EpisodeFileResource GetEpisodeFile(int id)
{
var episodeFile = _mediaFileService.Get(id);
var series = _seriesService.GetSeries(episodeFile.SeriesId);
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
}
private List<EpisodeFileResource> GetEpisodeFiles()
{
if (!Request.Query.SeriesId.HasValue)
{
throw new BadRequestException("seriesId is missing");
}
var seriesId = (int)Request.Query.SeriesId;
var series = _seriesService.GetSeries(seriesId);
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
}
private void SetQuality(EpisodeFileResource episodeFileResource)
{
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
episodeFile.Quality = episodeFileResource.Quality;
_mediaFileService.Update(episodeFile);
}*/
private void DeleteEpisodeFile(int id)
{
var episodeFile = _mediaFileService.GetMovie(id);
var series = _seriesService.GetMovie(episodeFile.MovieId);
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
_logger.Info("Deleting episode file: {0}", fullPath);
_recycleBinProvider.DeleteFile(fullPath);
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
}
public void Handle(EpisodeFileAddedEvent message)
{
BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.Id);
}
}
}

View File

@@ -116,6 +116,7 @@
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
<Compile Include="Indexers\ReleaseModuleBase.cs" />
<Compile Include="Indexers\ReleasePushModule.cs" />
<Compile Include="Movies\MovieFileModule.cs" />
<Compile Include="Movies\MovieModule.cs" />
<Compile Include="Movies\RenameMovieModule.cs" />
<Compile Include="Movies\RenameMovieResource.cs" />

View File

@@ -30,8 +30,8 @@ namespace NzbDrone.Api.Movie
public string ReleaseGroup { get; set; }
public QualityModel Quality { get; set; }
public MovieResource Movie { get; set; }
public string Edition { get; set; }
public Core.MediaFiles.MediaInfo.MediaInfoModel MediaInfo { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties)
}
@@ -63,7 +63,8 @@ namespace NzbDrone.Api.Movie
ReleaseGroup = model.ReleaseGroup,
Quality = model.Quality,
Movie = movie,
MediaInfo = model.MediaInfo,
Edition = model.Edition
};
}

View File

@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new DelugeSettings()
{
TvCategory = null
MovieCategory = null
};
_queued = new DelugeTorrent

View File

@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
Port = 2222,
Username = "admin",
Password = "pass",
TvCategory = "tv"
MovieCategory = "movies-radarr"
};
Mocker.GetMock<ITorrentFileInfoReader>()

View File

@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new RTorrentSettings()
{
TvCategory = null
MovieCategory = null
};
_downloading = new RTorrentTorrent

View File

@@ -112,12 +112,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
protected void GivenTvCategory()
{
_settings.TvCategory = "sonarr";
_settings.MovieCategory = "radarr";
}
protected void GivenTvDirectory()
{
_settings.TvDirectory = @"C:/Downloads/Finished/sonarr";
_settings.MovieDirectory = @"C:/Downloads/Finished/radarr";
}
protected void GivenFailedDownload()

File diff suppressed because it is too large Load Diff

View File

@@ -42,14 +42,14 @@ namespace NzbDrone.Core.Test.IndexerTests.OmgwtfnzbsTests
var releaseInfo = releases.First();
releaseInfo.Title.Should().Be("Stephen.Fry.Gadget.Man.S01E05.HDTV.x264-C4TV");
releaseInfo.Title.Should().Be("Un.Petit.Boulot.2016.FRENCH.720p.BluRay.DTS.x264-LOST");
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
releaseInfo.DownloadUrl.Should().Be("http://api.omgwtfnzbs.org/sn.php?id=OAl4g&user=nzbdrone&api=nzbdrone");
releaseInfo.InfoUrl.Should().Be("http://omgwtfnzbs.org/details.php?id=OAl4g");
releaseInfo.DownloadUrl.Should().Be("https://api.omgwtfnzbs.me/nzb/?id=8a2Bw&user=nzbdrone&api=nzbdrone");
releaseInfo.InfoUrl.Should().Be("https://omgwtfnzbs.me/details.php?id=8a2Bw");
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2012/12/17 23:30:13"));
releaseInfo.Size.Should().Be(236822906);
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2017/01/09 00:16:54"));
releaseInfo.Size.Should().Be(5354909355);
}
}
}

View File

@@ -0,0 +1,44 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(116)]
public class update_movie_sorttitle_again : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.WithConnection(SetSortTitles);
}
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand getSeriesCmd = conn.CreateCommand())
{
getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, Title FROM Movies";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var title = seriesReader.GetString(1);
var sortTitle = Parser.Parser.NormalizeTitle(title).ToLower();
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE Movies SET SortTitle = ? WHERE Id = ?";
updateCmd.AddParameter(sortTitle);
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(117)]
public class update_movie_file : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Column("Edition").OnTable("MovieFiles").AsString().Nullable();
//Execute.WithConnection(SetSortTitles);
}
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand getSeriesCmd = conn.CreateCommand())
{
getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, RelativePath FROM MovieFiles";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var relativePath = seriesReader.GetString(1);
var result = Parser.Parser.ParseMovieTitle(relativePath);
var edition = "";
if (result != null)
{
edition = Parser.Parser.ParseMovieTitle(relativePath).Edition;
}
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE MovieFiles SET Edition = ? WHERE Id = ?";
updateCmd.AddParameter(edition);
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,71 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
using System.Text;
using System.Text.RegularExpressions;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(118)]
public class update_movie_slug : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Execute.WithConnection(SetTitleSlug);
}
private void SetTitleSlug(IDbConnection conn, IDbTransaction tran)
{
using (IDbCommand getSeriesCmd = conn.CreateCommand())
{
getSeriesCmd.Transaction = tran;
getSeriesCmd.CommandText = @"SELECT Id, Title, Year FROM Movies";
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
{
while (seriesReader.Read())
{
var id = seriesReader.GetInt32(0);
var title = seriesReader.GetString(1);
var year = seriesReader.GetInt32(2);
var titleSlug = ToUrlSlug(title + "-" + year);
using (IDbCommand updateCmd = conn.CreateCommand())
{
updateCmd.Transaction = tran;
updateCmd.CommandText = "UPDATE Movies SET TitleSlug = ? WHERE Id = ?";
updateCmd.AddParameter(titleSlug);
updateCmd.AddParameter(id);
updateCmd.ExecuteNonQuery();
}
}
}
}
}
public static string ToUrlSlug(string value)
{
//First to lower case
value = value.ToLowerInvariant();
//Remove all accents
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
value = Encoding.ASCII.GetString(bytes);
//Replace spaces
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
//Trim dashes from end
value = value.Trim('-', '_');
//Replace double occurences of - or _
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return value;
}
}
}

View File

@@ -64,7 +64,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Movie.Profile, remoteEpisode.ParsedMovieInfo.Quality, subject.ParsedMovieInfo.Quality))
{
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedMovieInfo.Quality);
}
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteEpisode.ParsedMovieInfo.Quality);

View File

@@ -31,25 +31,17 @@ namespace NzbDrone.Core.Download.Clients.Deluge
_proxy = proxy;
}
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
_proxy.SetLabel(actualHash, Settings.MovieCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}*/
return actualHash.ToUpper();
}
@@ -57,66 +49,24 @@ namespace NzbDrone.Core.Download.Clients.Deluge
{
var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
_proxy.SetLabel(actualHash, Settings.MovieCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}*/
return actualHash.ToUpper();
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
var actualHash = _proxy.AddTorrentFromMagnet(magnetLink, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}
return actualHash.ToUpper();
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
var actualHash = _proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (!Settings.TvCategory.IsNullOrWhiteSpace())
{
_proxy.SetLabel(actualHash, Settings.TvCategory, Settings);
}
_proxy.SetTorrentConfiguration(actualHash, "remove_at_ratio", false, Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)DelugePriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)DelugePriority.First)
{
_proxy.MoveTorrentToTopInQueue(actualHash, Settings);
}
return actualHash.ToUpper();
throw new NotImplementedException("Episodes are not working with Radarr");
}
public override string Name => "Deluge";
@@ -127,9 +77,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
try
{
if (!Settings.TvCategory.IsNullOrWhiteSpace())
if (!Settings.MovieCategory.IsNullOrWhiteSpace())
{
torrents = _proxy.GetTorrentsByLabel(Settings.TvCategory, Settings);
torrents = _proxy.GetTorrentsByLabel(Settings.MovieCategory, Settings);
}
else
{
@@ -149,7 +99,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
var item = new DownloadClientItem();
item.DownloadId = torrent.Hash.ToUpper();
item.Title = torrent.Name;
item.Category = Settings.TvCategory;
item.Category = Settings.MovieCategory;
item.DownloadClient = Definition.Name;
@@ -280,7 +230,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
private ValidationFailure TestCategory()
{
if (Settings.TvCategory.IsNullOrWhiteSpace())
if (Settings.MovieCategory.IsNullOrWhiteSpace())
{
return null;
}
@@ -297,14 +247,14 @@ namespace NzbDrone.Core.Download.Clients.Deluge
var labels = _proxy.GetAvailableLabels(Settings);
if (!labels.Contains(Settings.TvCategory))
if (!labels.Contains(Settings.MovieCategory))
{
_proxy.AddLabel(Settings.TvCategory, Settings);
_proxy.AddLabel(Settings.MovieCategory, Settings);
labels = _proxy.GetAvailableLabels(Settings);
if (!labels.Contains(Settings.TvCategory))
if (!labels.Contains(Settings.MovieCategory))
{
return new NzbDroneValidationFailure("TvCategory", "Configuration of label failed")
return new NzbDroneValidationFailure("MovieCategory", "Configuration of label failed")
{
DetailedDescription = "Radarr as unable to add the label to Deluge."
};

View File

@@ -12,7 +12,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
RuleFor(c => c.Host).ValidHost();
RuleFor(c => c.Port).GreaterThan(0);
RuleFor(c => c.TvCategory).Matches("^[-a-z]*$").WithMessage("Allowed characters a-z and -");
RuleFor(c => c.MovieCategory).Matches("^[-a-z]*$").WithMessage("Allowed characters a-z and -");
}
}
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Download.Clients.Deluge
Host = "localhost";
Port = 8112;
Password = "deluge";
TvCategory = "movie-radarr";
MovieCategory = "movie-radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@@ -41,15 +41,9 @@ namespace NzbDrone.Core.Download.Clients.Deluge
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(DelugePriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(DelugePriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox)]
public bool UseSsl { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -33,81 +33,35 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
}
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, Byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
}
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
}
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}*/ //TODO: Maybe reimplement for movies
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteEpisode, string hash, string filename, Byte[] fileContent)
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, Byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentLabel(hash.ToLower(), Settings.TvCategory, Settings);
_proxy.SetTorrentLabel(hash.ToLower(), Settings.MovieCategory, Settings);
}
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)QBittorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)QBittorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash.ToLower(), Settings);
}*/
return hash;
}
@@ -236,7 +190,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
else if (version < 6)
{
// API version 6 introduced support for labels
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
return new NzbDroneValidationFailure("Category", "Category is not supported")
{
@@ -244,7 +198,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
};
}
}
else if (Settings.TvCategory.IsNullOrWhiteSpace())
else if (Settings.MovieCategory.IsNullOrWhiteSpace())
{
// warn if labels are supported, but category is not provided
return new NzbDroneValidationFailure("TvCategory", "Category is recommended")

View File

@@ -58,8 +58,8 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public List<QBittorrentTorrent> GetTorrents(QBittorrentSettings settings)
{
var request = BuildRequest(settings).Resource("/query/torrents")
.AddQueryParam("label", settings.TvCategory)
.AddQueryParam("category", settings.TvCategory);
.AddQueryParam("label", settings.MovieCategory)
.AddQueryParam("category", settings.MovieCategory);
var response = ProcessRequest<List<QBittorrentTorrent>>(request, settings);

View File

@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
{
Host = "localhost";
Port = 9091;
TvCategory = "movie-radarr";
MovieCategory = "movie-radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@@ -38,16 +38,9 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
public string Password { get; set; }
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
//Todo: update this shit.
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(QBittorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
[FieldDefinition(5, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Use a secure connection. See Options -> Web UI -> 'Use HTTPS instead of HTTP' in qBittorrent.")]
public bool UseSsl { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -30,13 +30,13 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
}
// patch can be a number (releases) or 'x' (git)
private static readonly Regex VersionRegex = new Regex(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+|x)(?<candidate>.*)", RegexOptions.Compiled);
private static readonly Regex VersionRegex = new Regex(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+|x)", RegexOptions.Compiled);
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContents)
{
var category = Settings.TvCategory;
var priority = remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority;
var response = _proxy.DownloadNzb(fileContents, filename, category, priority, Settings);
if (response != null && response.Ids.Any())
@@ -284,110 +284,103 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
failures.AddIfNotNull(TestCategory());
}
private bool HasVersion(int major, int minor, int patch = 0, string candidate = null)
private bool HasVersion(int major, int minor, int patch = 0)
{
candidate = candidate ?? string.Empty;
var rawVersion = _proxy.GetVersion(Settings);
var version = ParseVersion(rawVersion);
var version = _proxy.GetVersion(Settings);
if (version == null)
{
return false;
}
if (version.Major > major)
{
return true;
}
else if (version.Major < major)
{
return false;
}
if (version.Minor > minor)
{
return true;
}
else if (version.Minor < minor)
{
return false;
}
if (version.Build > patch)
{
return true;
}
else if (version.Build < patch)
{
return false;
}
return true;
}
private Version ParseVersion(string version)
{
var parsed = VersionRegex.Match(version);
int actualMajor;
int actualMinor;
int actualPatch;
string actualCandidate;
int major;
int minor;
int patch;
if (!parsed.Success)
if (parsed.Success)
{
major = Convert.ToInt32(parsed.Groups["major"].Value);
minor = Convert.ToInt32(parsed.Groups["minor"].Value);
patch = Convert.ToInt32(parsed.Groups["patch"].Value.Replace("x", "0"));
}
else
{
if (!version.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return false;
return null;
}
actualMajor = 1;
actualMinor = 1;
actualPatch = 0;
actualCandidate = null;
major = 1;
minor = 1;
patch = 0;
}
else
{
actualMajor = Convert.ToInt32(parsed.Groups["major"].Value);
actualMinor = Convert.ToInt32(parsed.Groups["minor"].Value);
actualPatch = Convert.ToInt32(parsed.Groups["patch"].Value.Replace("x", ""));
actualCandidate = parsed.Groups["candidate"].Value.ToUpper();
}
if (actualMajor > major)
{
return true;
}
else if (actualMajor < major)
{
return false;
}
if (actualMinor > minor)
{
return true;
}
else if (actualMinor < minor)
{
return false;
}
if (actualPatch > patch)
{
return true;
}
else if (actualPatch < patch)
{
return false;
}
if (actualCandidate.IsNullOrWhiteSpace())
{
return true;
}
else if (candidate.IsNullOrWhiteSpace())
{
return false;
}
else
{
return actualCandidate.CompareTo(candidate) > 0;
}
return new Version(major, minor, patch);
}
private ValidationFailure TestConnectionAndVersion()
{
try
{
var version = _proxy.GetVersion(Settings);
var parsed = VersionRegex.Match(version);
var rawVersion = _proxy.GetVersion(Settings);
var version = ParseVersion(rawVersion);
if (!parsed.Success)
if (version == null)
{
if (version.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
{
IsWarning = true,
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
};
}
return new ValidationFailure("Version", "Unknown Version: " + version);
}
var major = Convert.ToInt32(parsed.Groups["major"].Value);
var minor = Convert.ToInt32(parsed.Groups["minor"].Value);
if (rawVersion.Equals("develop", StringComparison.InvariantCultureIgnoreCase))
{
return new NzbDroneValidationFailure("Version", "Sabnzbd develop version, assuming version 1.1.0 or higher.")
{
IsWarning = true,
DetailedDescription = "Radarr may not be able to support new features added to SABnzbd when running develop versions."
};
}
if (major >= 1)
if (version.Major >= 1)
{
return null;
}
if (minor >= 7)
if (version.Minor >= 7)
{
return null;
}

View File

@@ -54,21 +54,21 @@ namespace NzbDrone.Core.Download.Clients.Transmission
var outputPath = new OsPath(torrent.DownloadDir);
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
{
if (!new OsPath(Settings.TvDirectory).Contains(outputPath)) continue;
if (!new OsPath(Settings.MovieDirectory).Contains(outputPath)) continue;
}
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
else if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
var directories = outputPath.FullPath.Split('\\', '/');
if (!directories.Contains(Settings.TvCategory)) continue;
if (!directories.Contains(Settings.MovieCategory)) continue;
}
outputPath = _remotePathMappingService.RemapRemoteToLocal(Settings.Host, outputPath);
var item = new DownloadClientItem();
item.DownloadId = torrent.HashString.ToUpper();
item.Category = Settings.TvCategory;
item.Category = Settings.MovieCategory;
item.Title = torrent.Name;
item.DownloadClient = Definition.Name;
@@ -123,9 +123,9 @@ namespace NzbDrone.Core.Download.Clients.Transmission
var config = _proxy.GetConfig(Settings);
var destDir = config.GetValueOrDefault("download-dir") as string;
if (Settings.TvCategory.IsNotNullOrWhiteSpace())
if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
destDir = string.Format("{0}/.{1}", destDir, Settings.TvCategory);
destDir = string.Format("{0}/.{1}", destDir, Settings.MovieCategory);
}
return new DownloadClientStatus
@@ -137,56 +137,23 @@ namespace NzbDrone.Core.Download.Clients.Transmission
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, GetDownloadDirectory(), Settings);
if (remoteMovie.Release.Age < 14 && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
remoteMovie.Release.Age > 14 && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteMovie, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromData(fileContent, GetDownloadDirectory(), Settings);
if (remoteMovie.Release.Age < 14 && Settings.RecentTvPriority == (int)TransmissionPriority.First ||
remoteMovie.Release.Age > 14 && Settings.OlderTvPriority == (int)TransmissionPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}
return hash;
}
@@ -204,16 +171,16 @@ namespace NzbDrone.Core.Download.Clients.Transmission
protected string GetDownloadDirectory()
{
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
{
return Settings.TvDirectory;
return Settings.MovieDirectory;
}
else if (Settings.TvCategory.IsNotNullOrWhiteSpace())
else if (Settings.MovieCategory.IsNotNullOrWhiteSpace())
{
var config = _proxy.GetConfig(Settings);
var destDir = (string)config.GetValueOrDefault("download-dir");
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.TvCategory);
return string.Format("{0}/{1}", destDir.TrimEnd('/'), Settings.MovieCategory);
}
else
{

View File

@@ -16,10 +16,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
RuleFor(c => c.UrlBase).ValidUrlBase();
RuleFor(c => c.TvCategory).Matches(@"^\.?[-a-z]*$", RegexOptions.IgnoreCase).WithMessage("Allowed characters a-z and -");
RuleFor(c => c.MovieCategory).Matches(@"^\.?[-a-z]*$", RegexOptions.IgnoreCase).WithMessage("Allowed characters a-z and -");
RuleFor(c => c.TvCategory).Empty()
.When(c => c.TvDirectory.IsNotNullOrWhiteSpace())
RuleFor(c => c.MovieCategory).Empty()
.When(c => c.MovieDirectory.IsNotNullOrWhiteSpace())
.WithMessage("Cannot use Category and Directory");
}
}
@@ -51,18 +51,12 @@ namespace NzbDrone.Core.Download.Clients.Transmission
public string Password { get; set; }
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional. Creates a [category] subdirectory in the output directory.")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(6, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default Transmission location")]
public string TvDirectory { get; set; }
public string MovieDirectory { get; set; }
[FieldDefinition(7, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing movies that we're released within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(8, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(TransmissionPriority), HelpText = "Priority to use when grabbing movies that we're released over 14 days ago")]
public int OlderTvPriority { get; set; }
[FieldDefinition(9, Label = "Use SSL", Type = FieldType.Checkbox)]
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
public bool UseSsl { get; set; }
public NzbDroneValidationResult Validate()

View File

@@ -37,51 +37,23 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
_rTorrentDirectoryValidator = rTorrentDirectoryValidator;
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
throw new NotImplementedException("Episodes are not working with Radarr");
}
protected override string AddFromMagnetLink(RemoteMovie remoteMovie, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
// Download the magnet to the appropriate directory.
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
//SetPriority(remoteEpisode, hash);
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
SetDownloadDirectory(hash);
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
// Schedule an event to apply the appropriate settings when that happens.
// var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
//_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
_proxy.StartTorrent(hash, Settings);
// Wait for the magnet to be resolved.
var tries = 10;
var retryDelay = 500;
if (WaitForTorrent(hash, tries, retryDelay))
{
return hash;
}
else
{
_logger.Warn("rTorrent could not resolve magnet within {0} seconds, download may remain stuck: {1}.", tries * retryDelay / 1000, magnetLink);
return hash;
}
}
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
// Download the magnet to the appropriate directory.
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
SetPriority(remoteEpisode, hash);
SetDownloadDirectory(hash);
// Once the magnet meta download finishes, rTorrent replaces it with the actual torrent download with default settings.
// Schedule an event to apply the appropriate settings when that happens.
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetDeferredMagnetProperties(hash, Settings.TvCategory, Settings.TvDirectory, priority, Settings);
_proxy.StartTorrent(hash, Settings);
// Wait for the magnet to be resolved.
@@ -107,13 +79,9 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
var retryDelay = 100;
if (WaitForTorrent(hash, tries, retryDelay))
{
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
//SetPriority(remoteEpisode, hash);
_proxy.SetTorrentLabel(hash, Settings.MovieCategory, Settings);
SetDownloadDirectory(hash);
_proxy.StartTorrent(hash, Settings);
return hash;
}
else
@@ -125,32 +93,6 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
}
}
protected override string AddFromTorrentFile(RemoteEpisode remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
var tries = 2;
var retryDelay = 100;
if (WaitForTorrent(hash, tries, retryDelay))
{
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
SetPriority(remoteEpisode, hash);
SetDownloadDirectory(hash);
_proxy.StartTorrent(hash, Settings);
return hash;
}
else
{
_logger.Debug("rTorrent could not add file");
RemoveItem(hash, true);
throw new ReleaseDownloadException(remoteEpisode.Release, "Downloading torrent failed");
}
}
public override string Name => "rTorrent";
public override ProviderMessage Message => new ProviderMessage("Radarr is unable to remove torrents that have finished seeding when using rTorrent", ProviderMessageType.Warning);
@@ -167,7 +109,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
foreach (RTorrentTorrent torrent in torrents)
{
// Don't concern ourselves with categories other than specified
if (torrent.Category != Settings.TvCategory) continue;
if (torrent.Category != Settings.MovieCategory) continue;
if (torrent.Path.StartsWith("."))
{
@@ -287,17 +229,11 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
return result.Errors.First();
}
private void SetPriority(RemoteEpisode remoteEpisode, string hash)
{
var priority = (RTorrentPriority)(remoteEpisode.IsRecentEpisode() ? Settings.RecentTvPriority : Settings.OlderTvPriority);
_proxy.SetTorrentPriority(hash, priority, Settings);
}
private void SetDownloadDirectory(string hash)
{
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
if (Settings.MovieDirectory.IsNotNullOrWhiteSpace())
{
_proxy.SetTorrentDownloadDirectory(hash, Settings.TvDirectory, Settings);
_proxy.SetTorrentDownloadDirectory(hash, Settings.MovieDirectory, Settings);
}
}

View File

@@ -18,13 +18,13 @@ namespace NzbDrone.Core.Download.Clients.rTorrent
DroneFactoryValidator droneFactoryValidator,
MappedNetworkDriveValidator mappedNetworkDriveValidator)
{
RuleFor(c => c.TvDirectory).Cascade(CascadeMode.StopOnFirstFailure)
RuleFor(c => c.MovieDirectory).Cascade(CascadeMode.StopOnFirstFailure)
.IsValidPath()
.SetValidator(rootFolderValidator)
.SetValidator(droneFactoryValidator)
.SetValidator(mappedNetworkDriveValidator)
.SetValidator(pathExistsValidator)
.When(c => c.TvDirectory.IsNotNullOrWhiteSpace())
.When(c => c.MovieDirectory.IsNotNullOrWhiteSpace())
.When(c => c.Host == "localhost" || c.Host == "127.0.0.1");
}
}

View File

@@ -11,7 +11,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
{
RuleFor(c => c.Host).ValidHost();
RuleFor(c => c.Port).InclusiveBetween(0, 65535);
RuleFor(c => c.TvCategory).NotEmpty()
RuleFor(c => c.MovieCategory).NotEmpty()
.WithMessage("A category is recommended")
.AsWarning();
}
@@ -26,9 +26,7 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
Host = "localhost";
Port = 8080;
UrlBase = "RPC2";
TvCategory = "movies-radarr";
OlderTvPriority = (int)RTorrentPriority.Normal;
RecentTvPriority = (int)RTorrentPriority.Normal;
MovieCategory = "movies-radarr";
}
[FieldDefinition(0, Label = "Host", Type = FieldType.Textbox)]
@@ -50,16 +48,10 @@ namespace NzbDrone.Core.Download.Clients.RTorrent
public string Password { get; set; }
[FieldDefinition(6, Label = "Category", Type = FieldType.Textbox, HelpText = "Adding a category specific to Radarr avoids conflicts with unrelated downloads, but it's optional.")]
public string TvCategory { get; set; }
public string MovieCategory { get; set; }
[FieldDefinition(7, Label = "Directory", Type = FieldType.Textbox, Advanced = true, HelpText = "Optional location to put downloads in, leave blank to use the default rTorrent location")]
public string TvDirectory { get; set; }
[FieldDefinition(8, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public int RecentTvPriority { get; set; }
[FieldDefinition(9, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(RTorrentPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public int OlderTvPriority { get; set; }
public string MovieDirectory { get; set; }
public NzbDroneValidationResult Validate()
{

View File

@@ -68,6 +68,38 @@ namespace NzbDrone.Core.Download.Clients.UTorrent
return hash;
}
protected override string AddFromMagnetLink(RemoteMovie remoteEpisode, string hash, string magnetLink)
{
_proxy.AddTorrentFromUrl(magnetLink, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)UTorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)UTorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}*/
return hash;
}
protected override string AddFromTorrentFile(RemoteMovie remoteEpisode, string hash, string filename, byte[] fileContent)
{
_proxy.AddTorrentFromFile(filename, fileContent, Settings);
_proxy.SetTorrentLabel(hash, Settings.TvCategory, Settings);
/*var isRecentEpisode = remoteEpisode.IsRecentEpisode();
if (isRecentEpisode && Settings.RecentTvPriority == (int)UTorrentPriority.First ||
!isRecentEpisode && Settings.OlderTvPriority == (int)UTorrentPriority.First)
{
_proxy.MoveTorrentToTopInQueue(hash, Settings);
}*/
return hash;
}
public override string Name => "uTorrent";
public override IEnumerable<DownloadClientItem> GetItems()

View File

@@ -94,34 +94,18 @@ namespace NzbDrone.Core.Download
return;
}
var series = _parsingService.GetSeries(trackedDownload.DownloadItem.Title);
if (series == null)
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
if (movie == null)
{
if (historyItem != null)
{
//series = _seriesService.GetSeries(historyItem.SeriesId);
movie = _movieService.GetMovie(historyItem.MovieId);
}
if (series == null)
if (movie == null)
{
var movie = _parsingService.GetMovie(trackedDownload.DownloadItem.Title);
if (movie == null)
{
if (historyItem != null)
{
movie = _movieService.GetMovie(historyItem.MovieId);
}
if (movie == null)
{
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
}
}
//trackedDownload.Warn("Series title mismatch, automatic import is not possible.");
//return;
trackedDownload.Warn("Movie title mismatch, automatic import is not possible.");
return;
}
}
}
@@ -132,61 +116,30 @@ namespace NzbDrone.Core.Download
private void Import(TrackedDownload trackedDownload)
{
var outputPath = trackedDownload.DownloadItem.OutputPath.FullPath;
if (trackedDownload.RemoteMovie.Movie != null)
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
if (importResults.Empty())
{
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
if (importResults.Empty())
{
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
return;
}
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= 1)
{
trackedDownload.State = TrackedDownloadStage.Imported;
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
return;
}
if (importResults.Any(c => c.Result != ImportResultType.Imported))
{
var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors))
.ToArray();
trackedDownload.Warn(statusMessages);
}
}
else if (trackedDownload.RemoteEpisode.Series != null)
{
var importResults = _downloadedEpisodesImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteEpisode.Series, trackedDownload.DownloadItem);
if (importResults.Empty())
{
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
return;
}
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count))
{
trackedDownload.State = TrackedDownloadStage.Imported;
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
return;
}
if (importResults.Any(c => c.Result != ImportResultType.Imported))
{
var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalEpisode.Path), v.Errors))
.ToArray();
trackedDownload.Warn(statusMessages);
}
trackedDownload.Warn("No files found are eligible for import in {0}", outputPath);
return;
}
if (importResults.Count(c => c.Result == ImportResultType.Imported) >= 1)
{
trackedDownload.State = TrackedDownloadStage.Imported;
_eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
return;
}
if (importResults.Any(c => c.Result != ImportResultType.Imported))
{
var statusMessages = importResults
.Where(v => v.Result != ImportResultType.Imported)
.Select(v => new TrackedDownloadStatusMessage(Path.GetFileName(v.ImportDecision.LocalMovie.Path), v.Errors))
.ToArray();
trackedDownload.Warn(statusMessages);
}
}
}
}

View File

@@ -13,8 +13,9 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
public void Clean()
{
CleanupOrphanedBySeries();
CleanupOrphanedByEpisode();
//CleanupOrphanedBySeries();
//CleanupOrphanedByEpisode();
CleanupOrphanedByMovie();
}
private void CleanupOrphanedBySeries()
@@ -29,6 +30,18 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
WHERE Series.Id IS NULL)");
}
private void CleanupOrphanedByMovie()
{
var mapper = _database.GetDataMapper();
mapper.ExecuteNonQuery(@"DELETE FROM History
WHERE Id IN (
SELECT History.Id FROM History
LEFT OUTER JOIN Movies
ON History.MovieId = Movies.Id
WHERE Movies.Id IS NULL)");
}
private void CleanupOrphanedByEpisode()
{
var mapper = _database.GetDataMapper();

View File

@@ -0,0 +1,30 @@
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHD : HttpIndexerBase<AwesomeHDSettings>
{
public override string Name => "AwesomeHD";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override bool SupportsRss => true;
public override bool SupportsSearch => true;
public override int PageSize => 50;
public AwesomeHD(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{ }
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new AwesomeHDRequestGenerator() { Settings = Settings };
}
public override IParseIndexerResponse GetParser()
{
return new AwesomeHDRssParser(Settings);
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using Newtonsoft.Json;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class Torrent
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "groupid")]
public string GroupId { get; set; }
[XmlElement(ElementName = "time")]
public DateTime Time { get; set; }
[XmlElement(ElementName = "userid")]
public string Userid { get; set; }
[XmlElement(ElementName = "size")]
public long Size { get; set; }
[XmlElement(ElementName = "snatched")]
public string Snatched { get; set; }
[XmlElement(ElementName = "seeders")]
public string Seeders { get; set; }
[XmlElement(ElementName = "leechers")]
public string Leechers { get; set; }
[XmlElement(ElementName = "releasegroup")]
public string Releasegroup { get; set; }
[XmlElement(ElementName = "resolution")]
public string Resolution { get; set; }
[XmlElement(ElementName = "media")]
public string Media { get; set; }
[XmlElement(ElementName = "format")]
public string Format { get; set; }
[XmlElement(ElementName = "encoding")]
public string Encoding { get; set; }
[XmlElement(ElementName = "audioformat")]
public string Audioformat { get; set; }
[XmlElement(ElementName = "audiobitrate")]
public string Audiobitrate { get; set; }
[XmlElement(ElementName = "audiochannels")]
public string Audiochannels { get; set; }
[XmlElement(ElementName = "subtitles")]
public string Subtitles { get; set; }
[XmlElement(ElementName = "encodestatus")]
public string Encodestatus { get; set; }
[XmlElement(ElementName = "freeleech")]
public string Freeleech { get; set; }
[XmlElement(ElementName = "cover")]
public string Cover { get; set; }
[XmlElement(ElementName = "smallcover")]
public string Smallcover { get; set; }
[XmlElement(ElementName = "year")]
public string Year { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "imdb")]
public string Imdb { get; set; }
[XmlElement(ElementName = "type")]
public string Type { get; set; }
[XmlElement(ElementName = "plotoutline")]
public string Plotoutline { get; set; }
}
public class SearchResults
{
[XmlElement(ElementName = "authkey")]
public string AuthKey { get; set; }
[XmlElement(ElementName = "torrent")]
public List<Torrent> Torrent { get; set; }
}
public class AwesomeHDSearchResponse
{
[XmlElement(ElementName = "?xml")]
public string Xml { get; set; }
[XmlElement(ElementName = "searchresults")]
public SearchResults SearchResults { get; set; }
}
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDRequestGenerator : IIndexerRequestGenerator
{
public AwesomeHDSettings Settings { get; set; }
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(null));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId));
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
{
if (searchParameters != null)
{
yield return new IndexerRequest(string.Format("{0}/searchapi.php?action=imdbsearch&passkey={1}&imdb={2}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim(), searchParameters), HttpAccept.Rss);
}
else
{
yield return new IndexerRequest(string.Format("{0}/searchapi.php?action=latestmovies&passkey={1}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim()), HttpAccept.Rss);
}
}
}
}

View File

@@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
using System;
using System.Linq;
using System.Xml;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDRssParser : IParseIndexerResponse
{
private readonly AwesomeHDSettings _settings;
public AwesomeHDRssParser(AwesomeHDSettings settings)
{
_settings = settings;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse,
"Unexpected response status {0} code from API request",
indexerResponse.HttpResponse.StatusCode);
}
// Hacky ¯\_(ツ)_/¯
XmlDocument doc = new XmlDocument();
doc.LoadXml(indexerResponse.Content);
var json = JsonConvert.SerializeXmlNode(doc);
Console.WriteLine(json);
var jsonResponse = JsonConvert.DeserializeObject<AwesomeHDSearchResponse>(json);
if (jsonResponse == null)
{
throw new IndexerException(indexerResponse, "Unexpected response from request");
}
foreach (var torrent in jsonResponse.SearchResults.Torrent)
{
var id = torrent.Id;
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.Audioformat}-{torrent.Releasegroup}";
torrentInfos.Add(new TorrentInfo()
{
Guid = string.Format("AwesomeHD-{0}", id),
Title = title,
Size = torrent.Size,
DownloadUrl = GetDownloadUrl(id, jsonResponse.SearchResults.AuthKey, _settings.Passkey),
InfoUrl = GetInfoUrl(torrent.GroupId, id),
Seeders = int.Parse(torrent.Seeders),
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
PublishDate = torrent.Time.ToUniversalTime()
});
}
return torrentInfos.OrderByDescending(o => ((dynamic)o).Seeders).ToArray();
}
private string GetDownloadUrl(string torrentId, string authKey, string passKey)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("action", "download")
.AddQueryParam("id", torrentId)
.AddQueryParam("authkey", authKey)
.AddQueryParam("torrent_pass", passKey);
return url.FullUri;
}
private string GetInfoUrl(string groupId, string torrentId)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("id", groupId)
.AddQueryParam("torrentid", torrentId);
return url.FullUri;
}
}
}

View File

@@ -0,0 +1,37 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDSettingsValidator : AbstractValidator<AwesomeHDSettings>
{
public AwesomeHDSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
RuleFor(c => c.Passkey).NotEmpty();
}
}
public class AwesomeHDSettings : IProviderConfig
{
private static readonly AwesomeHDSettingsValidator Validator = new AwesomeHDSettingsValidator();
public AwesomeHDSettings()
{
BaseUrl = "https://awesome-hd.me";
}
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since you Passkey will be sent to that host.")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Passkey")]
public string Passkey { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -39,14 +39,15 @@ namespace NzbDrone.Core.Indexers.Newznab
{
get
{
yield return GetDefinition("Dognzb.cr", GetSettings("https://api.dognzb.cr"));
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
yield return GetDefinition("DrunkenSlug", GetSettings("https://api.drunkenslug.com"));
yield return GetDefinition("Nzb-Tortuga", GetSettings("https://www.nzb-tortuga.com"));
yield return GetDefinition("Nzb.su", GetSettings("https://api.nzb.su"));
yield return GetDefinition("NZBCat", GetSettings("https://nzb.cat"));
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws", 5010, 5030, 5040, 5045));
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws"));
yield return GetDefinition("NZBgeek", GetSettings("https://api.nzbgeek.info"));
yield return GetDefinition("nzbplanet.net", GetSettings("https://api.nzbplanet.net"));
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org", 2000));
yield return GetDefinition("Nzbs.org", GetSettings("http://nzbs.org"));
yield return GetDefinition("OZnzb.com", GetSettings("https://api.oznzb.com"));
yield return GetDefinition("PFmonkey", GetSettings("https://www.pfmonkey.com"));
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));

View File

@@ -60,7 +60,7 @@ namespace NzbDrone.Core.Indexers.Newznab
public NewznabSettings()
{
Categories = new[] { 2030, 2035, 2040, 2045, 2050 };
Categories = new[] { 2000, 2010, 2020, 2030, 2035, 2040, 2045, 2050, 2060 };
AnimeCategories = Enumerable.Empty<int>();
}

View File

@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
protected override string GetInfoUrl(XElement item)
{
//Todo: Me thinks I need to parse details to get this...
var match = Regex.Match(item.Description(), @"(?:\<b\>View NZB\:\<\/b\>\s\<a\shref\=\"")(?<URL>.+)(?:\""\starget)",
var match = Regex.Match(item.Description(), @"(?:\<b\>View NZB\:\<\/b\>\s\<a\shref\=\"")(?<URL>.+)(?:\"")",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
if (match.Success)

View File

@@ -40,6 +40,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
torrentInfo.Seeders = torrent.seeders;
torrentInfo.Peers = torrent.leechers + torrent.seeders;
torrentInfo.Freeleech = torrent.freeleech;
torrentInfo.PublishDate = torrent.publishdate.ToUniversalTime();
results.Add(torrentInfo);
}

View File

@@ -78,9 +78,16 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
.Accept(HttpAccept.Json);
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
requestBuilder.AddQueryParam("user", Settings.User);
// requestBuilder.AddQueryParam("imdbid", "tt0076759"); //For now just search for Star Wars.
requestBuilder.AddQueryParam("search", "the"); // there has to be movies with 'the' in the title on any indexer
if (!string.IsNullOrWhiteSpace(Settings.User))
{
requestBuilder.AddQueryParam("user", Settings.User);
}
else
{
requestBuilder.AddQueryParam("user", "");
}
requestBuilder.AddQueryParam("search", "the");
yield return new IndexerRequest(requestBuilder.Build());
}
@@ -91,7 +98,15 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
.Accept(HttpAccept.Json);
requestBuilder.AddQueryParam("passkey", Settings.Passkey);
requestBuilder.AddQueryParam("user", Settings.User);
if (!string.IsNullOrWhiteSpace(Settings.User))
{
requestBuilder.AddQueryParam("user", Settings.User);
}
else
{
requestBuilder.AddQueryParam("user", "");
}
if (searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
{

View File

@@ -21,6 +21,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
public int size { get; set; }
public int leechers { get; set; }
public int seeders { get; set; }
public DateTime publishdate { get; set; }
}
}

View File

@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Indexers.TorrentPotato
public TorrentPotatoSettings()
{
BaseUrl = "";
BaseUrl = "http://127.0.0.1";
}
[FieldDefinition(0, Label = "API URL", HelpText = "URL to TorrentPotato api.")]

View File

@@ -97,8 +97,7 @@ namespace NzbDrone.Core.Indexers.Torznab
}
if (capabilities.SupportedTvSearchParameters != null &&
new[] { "q", "tvdbid", "rid" }.Any(v => capabilities.SupportedTvSearchParameters.Contains(v)) &&
new[] { "season", "ep" }.All(v => capabilities.SupportedTvSearchParameters.Contains(v)))
new[] { "q", "imdbid" }.Any(v => capabilities.SupportedTvSearchParameters.Contains(v)))
{
return null;
}

View File

@@ -39,10 +39,7 @@ namespace NzbDrone.Core.Indexers.Torznab
protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInfo)
{
var torrentInfo = base.ProcessItem(item, releaseInfo) as TorrentInfo;
torrentInfo.TvdbId = GetTvdbId(item);
torrentInfo.TvRageId = GetTvRageId(item);
torrentInfo.ImdbId = int.Parse(GetImdbId(item).Substring(2));
return torrentInfo;
}
@@ -100,31 +97,12 @@ namespace NzbDrone.Core.Indexers.Torznab
return url;
}
protected virtual int GetTvdbId(XElement item)
protected virtual string GetImdbId(XElement item)
{
var tvdbIdString = TryGetTorznabAttribute(item, "tvdbid");
int tvdbId;
if (!tvdbIdString.IsNullOrWhiteSpace() && int.TryParse(tvdbIdString, out tvdbId))
{
return tvdbId;
}
return 0;
var imdbIdString = TryGetTorznabAttribute(item, "imdbid");
return (!imdbIdString.IsNullOrWhiteSpace() ? imdbIdString.Substring(2) : null);
}
protected virtual int GetTvRageId(XElement item)
{
var tvRageIdString = TryGetTorznabAttribute(item, "rageid");
int tvRageId;
if (!tvRageIdString.IsNullOrWhiteSpace() && int.TryParse(tvRageIdString, out tvRageId))
{
return tvRageId;
}
return 0;
}
protected override string GetInfoHash(XElement item)
{
return TryGetTorznabAttribute(item, "infohash");

View File

@@ -178,7 +178,7 @@ namespace NzbDrone.Core.MediaFiles
_mediaFileTableCleanupService.Clean(movie, mediaFileList);
var decisionsStopwatch = Stopwatch.StartNew();
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie);
var decisions = _importDecisionMaker.GetImportDecisions(mediaFileList, movie, true);
decisionsStopwatch.Stop();
_logger.Trace("Import decisions complete for: {0} [{1}]", movie, decisionsStopwatch.Elapsed);

View File

@@ -183,7 +183,7 @@ namespace NzbDrone.Core.MediaFiles
}
}
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true);
var decisions = _importDecisionMaker.GetImportDecisions(videoFiles.ToList(), movie, folderInfo, true, false);
var importResults = _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
if ((downloadClientItem == null || !downloadClientItem.IsReadOnly) &&
@@ -237,7 +237,7 @@ namespace NzbDrone.Core.MediaFiles
}
}
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true);
var decisions = _importDecisionMaker.GetImportDecisions(new List<string>() { fileInfo.FullName }, movie, null, true, false);
return _importApprovedMovie.Import(decisions, true, downloadClientItem, importMode);
}

View File

@@ -83,6 +83,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
episodeFile.MediaInfo = localMovie.MediaInfo;
episodeFile.Movie = localMovie.Movie;
episodeFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
episodeFile.Edition = localMovie.ParsedMovieInfo.Edition;
bool copyOnly;
switch (importMode)

View File

@@ -19,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
{
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series);
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie);
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource); //TODO: Needs changing to ParsedMovieInfo!!
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality);
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality); //TODO: Needs changing to ParsedMovieInfo!!
List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource);
}
@@ -31,6 +32,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
private readonly IDiskProvider _diskProvider;
private readonly IVideoFileInfoReader _videoFileInfoReader;
private readonly IDetectSample _detectSample;
private readonly IQualityDefinitionService _qualitiesService;
private readonly Logger _logger;
public ImportDecisionMaker(IEnumerable<IImportDecisionEngineSpecification> specifications,
@@ -39,6 +41,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
IDiskProvider diskProvider,
IVideoFileInfoReader videoFileInfoReader,
IDetectSample detectSample,
IQualityDefinitionService qualitiesService,
Logger logger)
{
_specifications = specifications;
@@ -47,6 +50,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
_diskProvider = diskProvider;
_videoFileInfoReader = videoFileInfoReader;
_detectSample = detectSample;
_qualitiesService = qualitiesService;
_logger = logger;
}
@@ -57,7 +61,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie)
{
return GetImportDecisions(videoFiles, movie, null, false);
return GetImportDecisions(videoFiles, movie, null, true, false);
}
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, bool shouldCheckQuality = false)
{
return GetImportDecisions(videoFiles, movie, null, true, shouldCheckQuality);
}
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource)
@@ -77,7 +86,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
return decisions;
}
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource)
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldCheckQuality = false)
{
var newFiles = _mediaFileService.FilterExistingFiles(videoFiles.ToList(), movie);
@@ -88,13 +97,13 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
foreach (var file in newFiles)
{
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName));
decisions.AddIfNotNull(GetDecision(file, movie, folderInfo, sceneSource, shouldUseFolderName, shouldCheckQuality));
}
return decisions;
}
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
{
ImportDecision decision = null;
@@ -113,6 +122,106 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
if (sceneSource)
{
localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
if (shouldCheckQuality)
{
var width = localMovie.MediaInfo.Width;
var current = localMovie.Quality;
var qualityName = current.Quality.Name.ToLower();
QualityModel updated = null;
if (width > 1400)
{
if (qualityName.Contains("bluray"))
{
updated = new QualityModel(Quality.Bluray1080p);
}
else if (qualityName.Contains("webdl"))
{
updated = new QualityModel(Quality.WEBDL1080p);
}
else if (qualityName.Contains("hdtv"))
{
updated = new QualityModel(Quality.HDTV1080p);
}
else
{
var def = _qualitiesService.Get(Quality.HDTV1080p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.HDTV1080p);
}
def = _qualitiesService.Get(Quality.WEBDL1080p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.WEBDL1080p);
}
def = _qualitiesService.Get(Quality.Bluray1080p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.Bluray1080p);
}
if (updated == null)
{
updated = new QualityModel(Quality.Bluray1080p);
}
}
}
else
if (width > 900)
{
if (qualityName.Contains("bluray"))
{
updated = new QualityModel(Quality.Bluray720p);
}
else if (qualityName.Contains("webdl"))
{
updated = new QualityModel(Quality.WEBDL720p);
}
else if (qualityName.Contains("hdtv"))
{
updated = new QualityModel(Quality.HDTV720p);
}
else
{
var def = _qualitiesService.Get(Quality.HDTV720p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.HDTV720p);
}
def = _qualitiesService.Get(Quality.WEBDL720p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.WEBDL720p);
}
def = _qualitiesService.Get(Quality.Bluray720p);
if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
{
updated = new QualityModel(Quality.Bluray720p);
}
if (updated == null)
{
updated = new QualityModel(Quality.Bluray720p);
}
}
}
if (updated != null && updated != current)
{
updated.QualitySource = QualitySource.MediaInfo;
localMovie.Quality = updated;
}
}
decision = GetDecision(localMovie);
}
else

View File

@@ -161,7 +161,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
}
var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> { file },
movie, null, SceneSource(movie, folder));
movie, null, SceneSource(movie, folder), true);
return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : null;
}

View File

@@ -26,6 +26,7 @@ namespace NzbDrone.Core.MediaFiles
List<string> FilterExistingFiles(List<string> files, Series series);
List<string> FilterExistingFiles(List<string> files, Movie movie);
EpisodeFile Get(int id);
MovieFile GetMovie(int id);
List<EpisodeFile> Get(IEnumerable<int> ids);
List<MovieFile> GetMovies(IEnumerable<int> ids);
@@ -150,5 +151,9 @@ namespace NzbDrone.Core.MediaFiles
_movieFileRepository.Update(episodeFile);
}
public MovieFile GetMovie(int id)
{
return _movieFileRepository.Get(id);
}
}
}

View File

@@ -19,6 +19,7 @@ namespace NzbDrone.Core.MediaFiles
public string ReleaseGroup { get; set; }
public QualityModel Quality { get; set; }
public MediaInfoModel MediaInfo { get; set; }
public string Edition { get; set; }
public LazyLoaded<Movie> Movie { get; set; }
public override string ToString()

View File

@@ -13,6 +13,7 @@ using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Tv;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Text;
namespace NzbDrone.Core.MetadataSource.SkyHook
{
@@ -88,8 +89,9 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
movie.TmdbId = TmdbId;
movie.ImdbId = resource.imdb_id;
movie.Title = resource.title;
movie.TitleSlug = movie.Title.ToLower().Replace(" ", "-");
movie.TitleSlug = ToUrlSlug(movie.Title);
movie.CleanTitle = Parser.Parser.CleanSeriesTitle(movie.Title);
movie.SortTitle = Parser.Parser.NormalizeTitle(movie.Title);
movie.Overview = resource.overview;
movie.Website = resource.homepage;
if (resource.release_date.IsNotNullOrWhiteSpace())
@@ -98,11 +100,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
movie.Year = movie.InCinemas.Value.Year;
}
var slugResult = _movieService.FindByTitleSlug(movie.TitleSlug);
if (slugResult != null)
{
_logger.Debug("Movie with this title slug already exists. Adding year...");
}
movie.TitleSlug += "-" + movie.Year.ToString();
movie.Images.Add(_configService.GetCoverForURL(resource.poster_path, MediaCoverTypes.Poster));//TODO: Update to load image specs from tmdb page!
@@ -329,21 +326,18 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
{
imdbMovie.SortTitle = Parser.Parser.NormalizeTitle(result.title);
imdbMovie.Title = result.title;
string titleSlug = result.title;
string titleSlug = ToUrlSlug(result.title);
imdbMovie.TitleSlug = titleSlug.ToLower().Replace(" ", "-");
if (result.release_date.IsNotNullOrWhiteSpace())
{
imdbMovie.Year = DateTime.Parse(result.release_date).Year;
}
var slugResult = _movieService.FindByTitleSlug(imdbMovie.TitleSlug);
if (slugResult != null)
{
_logger.Debug("Movie with this title slug already exists. Adding year...");
}
//var slugResult = _movieService.FindByTitleSlug(imdbMovie.TitleSlug);
//if (slugResult != null)
//{
// _logger.Debug("Movie with this title slug already exists. Adding year...");
//}
imdbMovie.TitleSlug += "-" + imdbMovie.Year.ToString();
imdbMovie.Images = new List<MediaCover.MediaCover>();
@@ -524,5 +518,29 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
return MediaCoverTypes.Unknown;
}
}
public static string ToUrlSlug(string value)
{
//First to lower case
value = value.ToLowerInvariant();
//Remove all accents
var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
value = Encoding.ASCII.GetString(bytes);
//Replace spaces
value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);
//Remove invalid chars
value = Regex.Replace(value, @"[^a-z0-9\s-_]", "", RegexOptions.Compiled);
//Trim dashes from end
value = value.Trim('-', '_');
//Replace double occurences of - or _
value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);
return value;
}
}
}

View File

@@ -183,6 +183,9 @@
<Compile Include="Datastore\Migration\002_remove_tvrage_imdb_unique_constraint.cs" />
<Compile Include="Datastore\Migration\003_remove_clean_title_from_scene_mapping.cs" />
<Compile Include="Datastore\Migration\004_updated_history.cs" />
<Compile Include="Datastore\Migration\118_update_movie_slug.cs" />
<Compile Include="Datastore\Migration\117_update_movie_file.cs" />
<Compile Include="Datastore\Migration\116_update_movie_sorttitle_again.cs" />
<Compile Include="Datastore\Migration\115_update_movie_sorttitle.cs" />
<Compile Include="Datastore\Migration\111_remove_bitmetv.cs" />
<Compile Include="Datastore\Migration\112_remove_torrentleech.cs" />
@@ -578,6 +581,7 @@
<Compile Include="IndexerSearch\Definitions\MovieSearchCriteria.cs" />
<Compile Include="IndexerSearch\MoviesSearchCommand.cs" />
<Compile Include="IndexerSearch\MoviesSearchService.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDRssParser.cs" />
<Compile Include="Indexers\DownloadProtocol.cs" />
<Compile Include="Indexers\Exceptions\ApiKeyException.cs" />
<Compile Include="Indexers\Exceptions\IndexerException.cs" />
@@ -585,6 +589,10 @@
<Compile Include="Indexers\Exceptions\UnsupportedFeedException.cs" />
<Compile Include="Indexers\EzrssTorrentRssParser.cs" />
<Compile Include="Indexers\FetchAndParseRssService.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHD.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDApi.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDRequestGenerator.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDSettings.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcorn.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcornApi.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcornInfo.cs" />

View File

@@ -44,14 +44,14 @@ namespace NzbDrone.Core.Queue
private IEnumerable<Queue> MapQueue(TrackedDownload trackedDownload)
{
if (trackedDownload.RemoteEpisode.Episodes != null && trackedDownload.RemoteEpisode.Episodes.Any())
if (trackedDownload.RemoteEpisode != null && trackedDownload.RemoteEpisode.Episodes != null && trackedDownload.RemoteEpisode.Episodes.Any())
{
foreach (var episode in trackedDownload.RemoteEpisode.Episodes)
{
yield return MapEpisode(trackedDownload, episode);
}
}
else if (trackedDownload.RemoteMovie.Movie != null)
else if (trackedDownload.RemoteMovie != null && trackedDownload.RemoteMovie.Movie != null)
{
yield return MapMovie(trackedDownload, trackedDownload.RemoteMovie.Movie);
}

View File

@@ -1,18 +1,6 @@
<dl class="monitor-tooltip-contents">
<dt>All</dt>
<dd>Monitor all episodes except specials</dd>
<dt>Future</dt>
<dd>Monitor episodes that have not aired yet</dd>
<dt>Missing</dt>
<dd>Monitor episodes that do not have files or have not aired yet</dd>
<dt>Existing</dt>
<dd>Monitor episodes that have files or have not aired yet</dd>
<dt>First Season</dt>
<dd>Monitor all episodes of the first season. All other seasons will be ignored</dd>
<dt>Latest Season</dt>
<dd>Monitor all episodes of the latest season and future seasons</dd>
<dt>None</dt>
<dd>No episodes will be monitored.</dd>
<!--<dt>Latest Season</dt>-->
<!--<dd>Monitor all episodes the latest season only, previous seasons will be ignored</dd>-->
<dt>Yes</dt>
<dd>Monitor for new releases</dd>
<dt>No</dt>
<dd>Do not monitor for new releases</dd>
</dl>

View File

@@ -84,7 +84,7 @@ var view = Marionette.ItemView.extend({
content : content,
html : true,
trigger : 'hover',
title : 'Episode Monitoring Options',
title : 'Movie Monitoring Options',
placement : 'right',
container : this.$el
});

View File

@@ -18,14 +18,8 @@ module.exports = Backgrid.Cell.extend({
this.$el.empty();
if (this.model.get("movieFile")) {
var profileId = this.model.get("movieFile").quality.quality.id;
var profile = _.findWhere(ProfileCollection.models, { id : profileId });
if (profile) {
this.$el.html(profile.get('name'));
} else {
this.$el.html(this.model.get("movieFile").quality.quality.name);
}
}

View File

@@ -0,0 +1,15 @@
var NzbDroneCell = require('./NzbDroneCell');
module.exports = NzbDroneCell.extend({
className : 'file-title-cell',
render : function() {
this.$el.empty();
var title = this.model.get('relativePath');
this.$el.html(title);
return this;
}
});

View File

@@ -0,0 +1,23 @@
var NzbDroneCell = require('./NzbDroneCell');
module.exports = NzbDroneCell.extend({
className : 'release-title-cell',
render : function() {
this.$el.empty();
var info = this.model.get('mediaInfo');
if (info) {
var runtime = info.runTime;
if (runtime) {
runtime = runtime.split(".")[0];
}
var video = "{0} ({1}x{2}) ({3})".format(info.videoCodec, info.width, info.height, runtime);
var audio = "{0} ({1})".format(info.audioFormat, info.audioLanguages);
this.$el.html(video + " " + audio);
}
return this;
}
});

View File

@@ -32,10 +32,10 @@ module.exports = NzbDroneCell.extend({
this._setStatusWeight(1);
}
else if (!monitored) {
this.$el.html('<i class="icon-sonarr-series-unmonitored grid-icon" title="Not Monitored"></i>');
this._setStatusWeight(0);
}
// else if (!monitored) {
// this.$el.html('<i class="icon-sonarr-series-unmonitored grid-icon" title="Not Monitored"></i>');
// this._setStatusWeight(0);
// }
return this;
},

View File

@@ -1,5 +1,5 @@
{{#if_gt proper compare="1"}}
<span class="badge badge-info" title="PROPER">{{quality.name}}</span>
{{else}}
<span class="badge">{{quality.name}}</span>
{{/if_gt}}
<span class="badge" title="{{#if hardcodedSubs}}Warning: {{hardcodedSubs}}{{/if}}">{{quality.name}}</span>
{{/if_gt}}

View File

@@ -17,4 +17,4 @@ module.exports = NzbDroneCell.extend({
return this;
}
});
});

View File

@@ -15,12 +15,6 @@
<span class="label label-info">{{Bytes sizeOnDisk}}</span>
{{#if_eq fileCount compare="1"}}
<span class="label label-info"> 1 file</span>
{{else}}
<span class="label label-info"> {{fileCount}} files</span>
{{/if_eq}}
{{#if_eq status compare="released"}}
<span class="label label-info">{{inCinemas}}</span>
{{else}}

View File

@@ -11,6 +11,7 @@ var LoadingView = require('../../Shared/LoadingView');
var EpisodeFileEditorLayout = require('../../EpisodeFile/Editor/EpisodeFileEditorLayout');
var HistoryLayout = require('../History/MovieHistoryLayout');
var SearchLayout = require('../Search/MovieSearchLayout');
var FilesLayout = require("../Files/FilesLayout");
require('backstrech');
require('../../Mixins/backbone.signalr.mixin');
@@ -22,7 +23,8 @@ module.exports = Marionette.Layout.extend({
seasons : '#seasons',
info : '#info',
search : '#movie-search',
history : '#movie-history'
history : '#movie-history',
files : "#movie-files"
},
@@ -36,11 +38,12 @@ module.exports = Marionette.Layout.extend({
poster : '.x-movie-poster',
manualSearch : '.x-manual-search',
history : '.x-movie-history',
search : '.x-movie-search'
search : '.x-movie-search',
files : ".x-movie-files"
},
events : {
'click .x-episode-file-editor' : '_openEpisodeFileEditor',
'click .x-episode-file-editor' : '_showFiles',
'click .x-monitored' : '_toggleMonitored',
'click .x-edit' : '_editMovie',
'click .x-refresh' : '_refreshMovies',
@@ -48,7 +51,8 @@ module.exports = Marionette.Layout.extend({
'click .x-search' : '_moviesSearch',
'click .x-manual-search' : '_showSearch',
'click .x-movie-history' : '_showHistory',
'click .x-movie-search' : '_showSearch'
'click .x-movie-search' : '_showSearch',
"click .x-movie-files" : "_showFiles",
},
initialize : function() {
@@ -72,11 +76,18 @@ module.exports = Marionette.Layout.extend({
this.searchLayout = new SearchLayout({ model : this.model });
this.searchLayout.startManualSearch = true;
this.filesLayout = new FilesLayout({ model : this.model });
this._showBackdrop();
this._showSeasons();
this._setMonitoredState();
this._showInfo();
this._showHistory();
if (this.model.get("movieFile")) {
this._showFiles()
} else {
this._showHistory();
}
},
onRender : function() {
@@ -144,6 +155,15 @@ module.exports = Marionette.Layout.extend({
this.search.show(this.searchLayout);
},
_showFiles : function(e) {
if (e) {
e.preventDefault();
}
this.ui.files.tab('show');
this.files.show(this.filesLayout);
},
_toggleMonitored : function() {
var savePromise = this.model.save('monitored', !this.model.get('monitored'), { wait : true });

View File

@@ -9,7 +9,7 @@
{{title}}
<div class="movie-actions pull-right">
<div class="x-episode-file-editor">
<i class="icon-sonarr-episode-file" title="Modify episode files for movie"/>
<i class="icon-sonarr-episode-file" title="Modify movie files"/>
</div>
<div class="x-refresh">
<i class="icon-sonarr-refresh icon-can-spin" title="Update movie info and scan disk"/>
@@ -42,10 +42,12 @@
<ul class="nav nav-tabs" id="myTab">
<li><a href="#movie-history" class="x-movie-history">History</a></li>
<li><a href="#movie-search" class="x-movie-search">Search</a></li>
<li><a href="#movie-files" class="x-movie-files">Files</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane" id="movie-history"/>
<div class="tab-pane" id="movie-search"/>
<div class="tab-pane" id="movie-files"/>
</div>
</div>
</div>

View File

@@ -0,0 +1,26 @@
var vent = require('vent');
var Backgrid = require('backgrid');
module.exports = Backgrid.Cell.extend({
className : 'delete-episode-file-cell',
events : {
'click' : '_onClick'
},
render : function() {
this.$el.empty();
this.$el.html('<i class="icon-sonarr-delete" title="Delete movie file from disk"></i>');
return this;
},
_onClick : function() {
var self = this;
if (window.confirm('Are you sure you want to delete \'{0}\' from disk?'.format(this.model.get('relativePath')))) {
this.model.destroy().done(function() {
vent.trigger(vent.Events.MovieFileDeleted, { movieFile : self.model });
});
}
}
});

View File

@@ -0,0 +1,3 @@
var Backbone = require('backbone');
module.exports = Backbone.Model.extend({});

View File

@@ -0,0 +1,30 @@
var PagableCollection = require('backbone.pageable');
var FileModel = require('./FileModel');
var AsSortedCollection = require('../../Mixins/AsSortedCollection');
var Collection = PagableCollection.extend({
url : window.NzbDrone.ApiRoot + "/moviefile",
model : FileModel,
state : {
pageSize : 2000,
sortKey : 'title',
order : -1
},
mode : 'client',
sortMappings : {
'quality' : {
sortKey : "qualityWeight"
},
"edition" : {
sortKey : "edition"
}
},
});
Collection = AsSortedCollection.call(Collection);
module.exports = Collection;

View File

@@ -0,0 +1,107 @@
var vent = require('vent');
var Marionette = require('marionette');
var Backgrid = require('backgrid');
//var ButtonsView = require('./ButtonsView');
//var ManualSearchLayout = require('./ManualLayout');
var FilesCollection = require('./FilesCollection');
var CommandController = require('../../Commands/CommandController');
var LoadingView = require('../../Shared/LoadingView');
var NoResultsView = require('./NoFilesView');
var FileModel = require("./FileModel");
var FileTitleCell = require('../../Cells/FileTitleCell');
var FileSizeCell = require('../../Cells/FileSizeCell');
var QualityCell = require('../../Cells/QualityCell');
var MediaInfoCell = require('../../Cells/MediaInfoCell');
var ApprovalStatusCell = require('../../Cells/ApprovalStatusCell');
var DownloadReportCell = require('../../Release/DownloadReportCell');
var AgeCell = require('../../Release/AgeCell');
var ProtocolCell = require('../../Release/ProtocolCell');
var PeersCell = require('../../Release/PeersCell');
var EditionCell = require('../../Cells/EditionCell');
var DeleteFileCell = require("./DeleteFileCell");
module.exports = Marionette.Layout.extend({
template : 'Movies/Files/FilesLayoutTemplate',
regions : {
main : '#movie-files-region',
grid : "#movie-files-grid"
},
events : {
'click .x-search-auto' : '_searchAuto',
'click .x-search-manual' : '_searchManual',
'click .x-search-back' : '_showButtons'
},
columns : [
{
name : 'title',
label : 'Title',
cell : FileTitleCell
},
{
name : "mediaInfo",
label : "Media Info",
cell : MediaInfoCell
},
{
name : 'edition',
label : 'Edition',
cell : EditionCell,
title : "Edition",
},
{
name : 'size',
label : 'Size',
cell : FileSizeCell
},
{
name : 'quality',
label : 'Quality',
cell : QualityCell,
},
{
name : "delete",
label : "",
cell : DeleteFileCell,
}
],
initialize : function(movie) {
this.filesCollection = new FilesCollection();
var file = movie.model.get("movieFile");
this.filesCollection.add(file);
//this.listenTo(this.releaseCollection, 'sync', this._showSearchResults);
},
onShow : function() {
this.grid.show(new Backgrid.Grid({
row : Backgrid.Row,
columns : this.columns,
collection : this.filesCollection,
className : 'table table-hover'
}));
},
_showMainView : function() {
this.main.show(this.mainView);
},
_showButtons : function() {
this._showMainView();
},
_showSearchResults : function() {
if (this.releaseCollection.length === 0) {
this.mainView = new NoResultsView();
}
else {
//this.mainView = new ManualSearchLayout({ collection : this.releaseCollection });
}
this._showMainView();
}
});

View File

@@ -0,0 +1 @@
<div id="movie-files-region"><div id="movie-files-grid" class="table-responsive"></div></div>

View File

@@ -0,0 +1,5 @@
var Marionette = require('marionette');
module.exports = Marionette.ItemView.extend({
template : 'Movies/Files/NoFilesViewTemplate'
});

View File

@@ -0,0 +1,3 @@
<p class="text-warning">
No files for this movie.
</p>

View File

@@ -139,7 +139,7 @@ module.exports = Marionette.Layout.extend({
items : [
{
title : 'Title',
name : 'title'
name : 'sortTitle'
},
{
title : 'Quality',
@@ -175,6 +175,13 @@ module.exports = Marionette.Layout.extend({
tooltip : 'Monitored Only',
icon : 'icon-sonarr-monitored',
callback : this._setFilter
},
{
key : 'missing',
title : '',
tooltip : 'Missing Only',
icon : 'icon-sonarr-missing',
callback : this._setFilter
}
]
};

View File

@@ -65,9 +65,8 @@ var Collection = PageableCollection.extend({
true
],
'missing' : [
null,
null,
function(model) { return model.get('episodeCount') !== model.get('episodeFileCount'); }
'downloaded',
false
]
},