mirror of
https://github.com/Radarr/Radarr.git
synced 2026-04-18 21:35:51 -04:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 520836f475 | |||
| 6d6bf1044b | |||
| 195866f3aa | |||
| 10f0be0708 | |||
| 721773ef68 | |||
| 0d647ffb9a | |||
| b6235e99c8 | |||
| 1d0a6af7d7 | |||
| efd7af165c | |||
| 3f4ee6d841 | |||
| 55c437d980 | |||
| ecfe103c50 | |||
| a282ad7809 | |||
| 64176b8d26 | |||
| 278fb298b6 | |||
| 1d1b88cf05 | |||
| 0c50aa7872 | |||
| 0bfa01f072 | |||
| 3e9594f069 | |||
| a07138680b | |||
| 5f6f2f2859 | |||
| e185ba0191 | |||
| 3ab0b17379 | |||
| 942d97931e | |||
| 40809f1d91 | |||
| f6a37186aa |
@@ -25,9 +25,9 @@ namespace NzbDrone.Api.Indexers
|
|||||||
|
|
||||||
release.ReleaseWeight = initialWeight;
|
release.ReleaseWeight = initialWeight;
|
||||||
|
|
||||||
if (decision.RemoteEpisode.Series != null)
|
if (decision.RemoteMovie.Movie != null)
|
||||||
{
|
{
|
||||||
release.QualityWeight = decision.RemoteEpisode.Series
|
release.QualityWeight = decision.RemoteMovie.Movie
|
||||||
.Profile.Value
|
.Profile.Value
|
||||||
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ namespace NzbDrone.Api.RootFolders
|
|||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
//FreeSpace
|
FreeSpace = resource.FreeSpace,
|
||||||
//UnmappedFolders
|
UnmappedFolders = resource.UnmappedFolders
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteMovie subject, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
if (subject.Movie.MovieFile.Value != null)
|
if (subject.Movie.MovieFile.Value != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -39,7 +39,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
var profile = subject.Movie.Profile.Value;
|
var profile = subject.Movie.Profile.Value;
|
||||||
var delayProfile = _delayProfileService.BestForTags(subject.Movie.Tags);
|
var delayProfile = _delayProfileService.BestForTags(subject.Movie.Tags);
|
||||||
var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol);
|
var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol);
|
||||||
var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol;
|
var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol;
|
||||||
|
|
||||||
|
// Preferred word count
|
||||||
|
var title = subject.Release.Title;
|
||||||
|
var preferredWords = subject.Movie.Profile.Value.PreferredTags;
|
||||||
|
var preferredCount = preferredWords.AsEnumerable().Count(w => title.ToLower().Contains(w.ToLower()));
|
||||||
|
|
||||||
|
|
||||||
if (delay == 0)
|
if (delay == 0)
|
||||||
{
|
{
|
||||||
@@ -49,7 +55,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
|
|
||||||
var comparer = new QualityModelComparer(profile);
|
var comparer = new QualityModelComparer(profile);
|
||||||
|
|
||||||
if (isPreferredProtocol)
|
if (isPreferredProtocol && (subject.Movie.MovieFileId != 0) && (preferredCount > 0 || preferredWords == null))
|
||||||
{
|
{
|
||||||
var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, subject.Movie.MovieFile.Value.Quality, subject.ParsedMovieInfo.Quality);
|
var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, subject.Movie.MovieFile.Value.Quality, subject.ParsedMovieInfo.Quality);
|
||||||
|
|
||||||
@@ -59,7 +65,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
|
|
||||||
if (revisionUpgrade)
|
if (revisionUpgrade)
|
||||||
{
|
{
|
||||||
_logger.Debug("New quality is a better revision for existing quality, skipping delay");
|
_logger.Debug("New quality is a better revision for existing quality and preferred word count is {0}, skipping delay", preferredCount);
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,11 +74,11 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
|
|
||||||
// If quality meets or exceeds the best allowed quality in the profile accept it immediately
|
// If quality meets or exceeds the best allowed quality in the profile accept it immediately
|
||||||
var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality());
|
var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality());
|
||||||
var isBestInProfile = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile) >= 0;
|
var isBestInProfile = comparer.Compare(subject.ParsedMovieInfo.Quality, bestQualityInProfile) >= 0;
|
||||||
|
|
||||||
if (isBestInProfile && isPreferredProtocol)
|
if (isBestInProfile && isPreferredProtocol && (preferredCount > 0 || preferredWords == null))
|
||||||
{
|
{
|
||||||
_logger.Debug("Quality is highest in profile for preferred protocol, will not delay");
|
_logger.Debug("Quality is highest in profile for preferred protocol and preferred word count is {0}, will not delay.", preferredCount);
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,13 +88,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||||||
if (oldest != null && oldest.Release.AgeMinutes > delay)
|
if (oldest != null && oldest.Release.AgeMinutes > delay)
|
||||||
{
|
{
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (subject.Release.AgeMinutes < delay)
|
if (subject.Release.AgeMinutes < delay)
|
||||||
{
|
{
|
||||||
_logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol);
|
_logger.Debug("Waiting for better quality release, There is a {0} minute delay on {1}", delay, subject.Release.DownloadProtocol);
|
||||||
return Decision.Reject("Waiting for better quality release");
|
return Decision.Reject("Waiting for better quality release");
|
||||||
}*/ //TODO: Update for movies!
|
} //TODO: Update for movies!
|
||||||
|
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,12 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
|||||||
|
|
||||||
private int GetMinimumAllowedRuntime(Movie movie)
|
private int GetMinimumAllowedRuntime(Movie movie)
|
||||||
{
|
{
|
||||||
return 360; //6 minutes
|
if (movie.Runtime < 1)
|
||||||
|
{
|
||||||
|
return 5 * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
return movie.Runtime / 5 * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetMinimumAllowedRuntime(Series series)
|
private int GetMinimumAllowedRuntime(Series series)
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
//List<MovieFile> Get(IEnumerable<int> ids);
|
//List<MovieFile> Get(IEnumerable<int> ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MediaFileService : IMediaFileService, IHandleAsync<SeriesDeletedEvent>
|
public class MediaFileService : IMediaFileService, IHandleAsync<SeriesDeletedEvent>,
|
||||||
|
IHandleAsync<MovieDeletedEvent>
|
||||||
{
|
{
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IMediaFileRepository _mediaFileRepository;
|
private readonly IMediaFileRepository _mediaFileRepository;
|
||||||
@@ -155,5 +156,14 @@ namespace NzbDrone.Core.MediaFiles
|
|||||||
{
|
{
|
||||||
return _movieFileRepository.Get(id);
|
return _movieFileRepository.Get(id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void HandleAsync(MovieDeletedEvent message)
|
||||||
|
{
|
||||||
|
if (message.DeleteFiles == true)
|
||||||
|
{
|
||||||
|
var files = GetFilesByMovie(message.Movie.Id);
|
||||||
|
_movieFileRepository.DeleteMany(files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,9 +21,18 @@ namespace NzbDrone.Core.NetImport.Trakt
|
|||||||
|
|
||||||
public class TraktResponse
|
public class TraktResponse
|
||||||
{
|
{
|
||||||
public int rank { get; set; }
|
public int? rank { get; set; }
|
||||||
public string listed_at { get; set; }
|
public string listed_at { get; set; }
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
|
|
||||||
|
public int? watchers { get; set; }
|
||||||
|
|
||||||
|
public long? revenue { get; set; }
|
||||||
|
|
||||||
|
public long? watcher_count { get; set; }
|
||||||
|
public long? play_count { get; set; }
|
||||||
|
public long? collected_count { get; set; }
|
||||||
|
|
||||||
public Movie movie { get; set; }
|
public Movie movie { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,32 @@
|
|||||||
namespace NzbDrone.Core.NetImport.Trakt
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.NetImport.Trakt
|
||||||
{
|
{
|
||||||
public enum TraktListType
|
public enum TraktListType
|
||||||
{
|
{
|
||||||
WatchList = 0,
|
[EnumMember(Value = "User Watch List")]
|
||||||
Watched = 1,
|
UserWatchList = 0,
|
||||||
CustomList = 2
|
[EnumMember(Value = "User Watched List")]
|
||||||
|
UserWatchedList = 1,
|
||||||
|
[EnumMember(Value = "User Custom List")]
|
||||||
|
UserCustomList = 2,
|
||||||
|
|
||||||
|
[EnumMember(Value = "Trending Movies")]
|
||||||
|
TrendingMovies = 3,
|
||||||
|
[EnumMember(Value = "Popular Movies")]
|
||||||
|
PopularMovies = 4,
|
||||||
|
[EnumMember(Value = "Top Anticipated Movies")]
|
||||||
|
AnticipatedMovies = 5,
|
||||||
|
[EnumMember(Value = "Top Box Office Movies")]
|
||||||
|
BoxOfficeMovies = 6,
|
||||||
|
|
||||||
|
[EnumMember(Value = "Top Watched Movies By Week")]
|
||||||
|
TopWatchedByWeek = 7,
|
||||||
|
[EnumMember(Value = "Top Watched Movies By Month")]
|
||||||
|
TopWatchedByMonth = 8,
|
||||||
|
[EnumMember(Value = "Top Watched Movies By Year")]
|
||||||
|
TopWatchedByYear = 9,
|
||||||
|
[EnumMember(Value = "Top Watched Movies Of All Time")]
|
||||||
|
TopWatchedByAllTime = 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,26 +42,45 @@ namespace NzbDrone.Core.NetImport.Trakt
|
|||||||
return movies;
|
return movies;
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonResponse = JsonConvert.DeserializeObject<List<TraktResponse>>(_importResponse.Content);
|
if (_settings.ListType == (int) TraktListType.PopularMovies)
|
||||||
|
|
||||||
// no movies were return
|
|
||||||
if (jsonResponse == null)
|
|
||||||
{
|
{
|
||||||
return movies;
|
var jsonResponse = JsonConvert.DeserializeObject<List<Movie>>(_importResponse.Content);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var movie in jsonResponse)
|
foreach (var movie in jsonResponse)
|
||||||
{
|
|
||||||
movies.AddIfNotNull(new Tv.Movie()
|
|
||||||
{
|
{
|
||||||
Title = movie.movie.title,
|
movies.AddIfNotNull(new Tv.Movie()
|
||||||
ImdbId = movie.movie.ids.imdb,
|
{
|
||||||
TmdbId = movie.movie.ids.tmdb,
|
Title = movie.title,
|
||||||
Year = (movie.movie.year ?? 0)
|
ImdbId = movie.ids.imdb,
|
||||||
});
|
TmdbId = movie.ids.tmdb,
|
||||||
|
Year = (movie.year ?? 0)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var jsonResponse = JsonConvert.DeserializeObject<List<TraktResponse>>(_importResponse.Content);
|
||||||
|
|
||||||
|
// no movies were return
|
||||||
|
if (jsonResponse == null)
|
||||||
|
{
|
||||||
|
return movies;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var movie in jsonResponse)
|
||||||
|
{
|
||||||
|
movies.AddIfNotNull(new Tv.Movie()
|
||||||
|
{
|
||||||
|
Title = movie.movie.title,
|
||||||
|
ImdbId = movie.movie.ids.imdb,
|
||||||
|
TmdbId = movie.movie.ids.tmdb,
|
||||||
|
Year = (movie.movie.year ?? 0)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return movies;
|
return movies;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool PreProcess(NetImportResponse indexerResponse)
|
protected virtual bool PreProcess(NetImportResponse indexerResponse)
|
||||||
|
|||||||
@@ -21,18 +21,42 @@ namespace NzbDrone.Core.NetImport.Trakt
|
|||||||
|
|
||||||
private IEnumerable<NetImportRequest> GetMovies(string searchParameters)
|
private IEnumerable<NetImportRequest> GetMovies(string searchParameters)
|
||||||
{
|
{
|
||||||
var link = $"{Settings.Link.Trim()}{Settings.Username.Trim()}";
|
var link = Settings.Link.Trim();
|
||||||
|
|
||||||
switch (Settings.ListType)
|
switch (Settings.ListType)
|
||||||
{
|
{
|
||||||
case (int)TraktListType.CustomList:
|
case (int)TraktListType.UserCustomList:
|
||||||
link = link + $"/lists/{Settings.Listname.Trim()}/items/movies";
|
link = link + $"/users/{Settings.Username.Trim()}/lists/{Settings.Listname.Trim()}/items/movies";
|
||||||
break;
|
break;
|
||||||
case (int)TraktListType.WatchList:
|
case (int)TraktListType.UserWatchList:
|
||||||
link = link + "/watchlist/movies";
|
link = link + $"/users/{Settings.Username.Trim()}/watchlist/movies";
|
||||||
break;
|
break;
|
||||||
case (int)TraktListType.Watched:
|
case (int)TraktListType.UserWatchedList:
|
||||||
link = link + "/watched/movies";
|
link = link + $"/users/{Settings.Username.Trim()}/watched/movies";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.TrendingMovies:
|
||||||
|
link = link + "/movies/trending";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.PopularMovies:
|
||||||
|
link = link + "/movies/popular";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.AnticipatedMovies:
|
||||||
|
link = link + "/movies/anticipated";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.BoxOfficeMovies:
|
||||||
|
link = link + "/movies/boxoffice";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.TopWatchedByWeek:
|
||||||
|
link = link + "/movies/watched/weekly";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.TopWatchedByMonth:
|
||||||
|
link = link + "/movies/watched/monthly";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.TopWatchedByYear:
|
||||||
|
link = link + "/movies/watched/yearly";
|
||||||
|
break;
|
||||||
|
case (int)TraktListType.TopWatchedByAllTime:
|
||||||
|
link = link + "/movies/watched/all";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.ThingiProvider;
|
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
namespace NzbDrone.Core.NetImport.Trakt
|
namespace NzbDrone.Core.NetImport.Trakt
|
||||||
@@ -20,7 +18,7 @@ namespace NzbDrone.Core.NetImport.Trakt
|
|||||||
{
|
{
|
||||||
public TraktSettings()
|
public TraktSettings()
|
||||||
{
|
{
|
||||||
Link = "https://api.trakt.tv/users/";
|
Link = "https://api.trakt.tv";
|
||||||
Username = "";
|
Username = "";
|
||||||
Listname = "";
|
Listname = "";
|
||||||
}
|
}
|
||||||
@@ -31,7 +29,7 @@ namespace NzbDrone.Core.NetImport.Trakt
|
|||||||
[FieldDefinition(1, Label = "Trakt List Type", Type = FieldType.Select, SelectOptions = typeof(TraktListType), HelpText = "Trakt list type, custom or watchlist")]
|
[FieldDefinition(1, Label = "Trakt List Type", Type = FieldType.Select, SelectOptions = typeof(TraktListType), HelpText = "Trakt list type, custom or watchlist")]
|
||||||
public int ListType { get; set; }
|
public int ListType { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(2, Label = "Trakt Username", HelpText = "Trakt Username the list belongs to.")]
|
[FieldDefinition(2, Label = "Trakt Username", HelpText = "Required for User List")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(3, Label = "Trakt List Name", HelpText = "Required for Custom List")]
|
[FieldDefinition(3, Label = "Trakt List Name", HelpText = "Required for Custom List")]
|
||||||
@@ -39,4 +37,6 @@ namespace NzbDrone.Core.NetImport.Trakt
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
<Reference Include="System.Web" />
|
<Reference Include="System.Web" />
|
||||||
<Reference Include="System.Web.Extensions" />
|
<Reference Include="System.Web.Extensions" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
|||||||
@@ -323,6 +323,12 @@ namespace NzbDrone.Core.Organizer
|
|||||||
public static string TitleThe(string title)
|
public static string TitleThe(string title)
|
||||||
{
|
{
|
||||||
string[] prefixes = { "The ", "An ", "A " };
|
string[] prefixes = { "The ", "An ", "A " };
|
||||||
|
|
||||||
|
if (title.Length < 5)
|
||||||
|
{
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (string prefix in prefixes)
|
foreach (string prefix in prefixes)
|
||||||
{
|
{
|
||||||
int prefix_length = prefix.Length;
|
int prefix_length = prefix.Length;
|
||||||
@@ -724,6 +730,10 @@ namespace NzbDrone.Core.Organizer
|
|||||||
case "E-AC-3":
|
case "E-AC-3":
|
||||||
audioCodec = "EAC3";
|
audioCodec = "EAC3";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "Atmos / TrueHD":
|
||||||
|
audioCodec = "Atmos TrueHD";
|
||||||
|
break;
|
||||||
|
|
||||||
case "MPEG Audio":
|
case "MPEG Audio":
|
||||||
if (movieFile.MediaInfo.AudioProfile == "Layer 3")
|
if (movieFile.MediaInfo.AudioProfile == "Layer 3")
|
||||||
@@ -737,7 +747,26 @@ namespace NzbDrone.Core.Organizer
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "DTS":
|
case "DTS":
|
||||||
audioCodec = movieFile.MediaInfo.AudioFormat;
|
if (movieFile.MediaInfo.AudioProfile == "ES" || movieFile.MediaInfo.AudioProfile == "ES Discrete" || movieFile.MediaInfo.AudioProfile == "ES Matrix")
|
||||||
|
{
|
||||||
|
audioCodec = "DTS-ES";
|
||||||
|
}
|
||||||
|
else if (movieFile.MediaInfo.AudioProfile == "MA")
|
||||||
|
{
|
||||||
|
audioCodec = "DTS-HD MA";
|
||||||
|
}
|
||||||
|
else if (movieFile.MediaInfo.AudioProfile == "HRA")
|
||||||
|
{
|
||||||
|
audioCodec = "DTS-HD HRA";
|
||||||
|
}
|
||||||
|
else if (movieFile.MediaInfo.AudioProfile == "X")
|
||||||
|
{
|
||||||
|
audioCodec = "DTS-X";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audioCodec = movieFile.MediaInfo.AudioFormat;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ namespace NzbDrone.Core.RootFolders
|
|||||||
private readonly IRootFolderRepository _rootFolderRepository;
|
private readonly IRootFolderRepository _rootFolderRepository;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly ISeriesRepository _seriesRepository;
|
private readonly ISeriesRepository _seriesRepository;
|
||||||
|
private readonly IMovieRepository _movieRepository;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
@@ -44,12 +45,14 @@ namespace NzbDrone.Core.RootFolders
|
|||||||
public RootFolderService(IRootFolderRepository rootFolderRepository,
|
public RootFolderService(IRootFolderRepository rootFolderRepository,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
ISeriesRepository seriesRepository,
|
ISeriesRepository seriesRepository,
|
||||||
|
IMovieRepository movieRepository,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_rootFolderRepository = rootFolderRepository;
|
_rootFolderRepository = rootFolderRepository;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_seriesRepository = seriesRepository;
|
_seriesRepository = seriesRepository;
|
||||||
|
_movieRepository = movieRepository;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@@ -128,6 +131,41 @@ namespace NzbDrone.Core.RootFolders
|
|||||||
_rootFolderRepository.Delete(id);
|
_rootFolderRepository.Delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//private List<UnmappedFolder> GetUnmappedFolders(string path)
|
||||||
|
//{
|
||||||
|
// _logger.Debug("Generating list of unmapped folders");
|
||||||
|
// if (string.IsNullOrEmpty(path))
|
||||||
|
// throw new ArgumentException("Invalid path provided", "path");
|
||||||
|
|
||||||
|
// var results = new List<UnmappedFolder>();
|
||||||
|
// var series = _seriesRepository.All().ToList();
|
||||||
|
|
||||||
|
// if (!_diskProvider.FolderExists(path))
|
||||||
|
// {
|
||||||
|
// _logger.Debug("Path supplied does not exist: {0}", path);
|
||||||
|
// return results;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var seriesFolders = _diskProvider.GetDirectories(path).ToList();
|
||||||
|
// var unmappedFolders = seriesFolders.Except(series.Select(s => s.Path), PathEqualityComparer.Instance).ToList();
|
||||||
|
|
||||||
|
// foreach (string unmappedFolder in unmappedFolders)
|
||||||
|
// {
|
||||||
|
// var di = new DirectoryInfo(unmappedFolder.Normalize());
|
||||||
|
// if (!di.Attributes.HasFlag(FileAttributes.System) && !di.Attributes.HasFlag(FileAttributes.Hidden))
|
||||||
|
// {
|
||||||
|
// results.Add(new UnmappedFolder { Name = di.Name, Path = di.FullName });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var setToRemove = SpecialFolders;
|
||||||
|
// results.RemoveAll(x => setToRemove.Contains(new DirectoryInfo(x.Path.ToLowerInvariant()).Name));
|
||||||
|
|
||||||
|
// _logger.Debug("{0} unmapped folders detected.", results.Count);
|
||||||
|
// return results;
|
||||||
|
//}
|
||||||
|
|
||||||
private List<UnmappedFolder> GetUnmappedFolders(string path)
|
private List<UnmappedFolder> GetUnmappedFolders(string path)
|
||||||
{
|
{
|
||||||
_logger.Debug("Generating list of unmapped folders");
|
_logger.Debug("Generating list of unmapped folders");
|
||||||
@@ -135,7 +173,7 @@ namespace NzbDrone.Core.RootFolders
|
|||||||
throw new ArgumentException("Invalid path provided", "path");
|
throw new ArgumentException("Invalid path provided", "path");
|
||||||
|
|
||||||
var results = new List<UnmappedFolder>();
|
var results = new List<UnmappedFolder>();
|
||||||
var series = _seriesRepository.All().ToList();
|
var movies = _movieRepository.All().ToList();
|
||||||
|
|
||||||
if (!_diskProvider.FolderExists(path))
|
if (!_diskProvider.FolderExists(path))
|
||||||
{
|
{
|
||||||
@@ -143,8 +181,8 @@ namespace NzbDrone.Core.RootFolders
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
var seriesFolders = _diskProvider.GetDirectories(path).ToList();
|
var movieFolders = _diskProvider.GetDirectories(path).ToList();
|
||||||
var unmappedFolders = seriesFolders.Except(series.Select(s => s.Path), PathEqualityComparer.Instance).ToList();
|
var unmappedFolders = movieFolders.Except(movies.Select(s => s.Path), PathEqualityComparer.Instance).ToList();
|
||||||
|
|
||||||
foreach (string unmappedFolder in unmappedFolders)
|
foreach (string unmappedFolder in unmappedFolders)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ module.exports = Marionette.Layout.extend({
|
|||||||
|
|
||||||
_folderSelected : function(options) {
|
_folderSelected : function(options) {
|
||||||
vent.trigger(vent.Commands.CloseModalCommand);
|
vent.trigger(vent.Commands.CloseModalCommand);
|
||||||
this.ui.$existing.show();
|
//this.ui.$existing.show();
|
||||||
this.workspace.show(new ExistingMoviesCollectionView({ model : options.model }));
|
this.workspace.show(new ExistingMoviesCollectionView({ model : options.model }));
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ module.exports = Marionette.Layout.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_addFromList : function() {
|
_addFromList : function() {
|
||||||
this.ui.$existing.hide();
|
//this.ui.$existing.hide();
|
||||||
this.workspace.show(new AddFromListView());
|
this.workspace.show(new AddFromListView());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ module.exports = Marionette.Layout.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updateUrl : function() {
|
_updateUrl : function() {
|
||||||
var icalUrl = window.location.host + StatusModel.get('urlBase') + '/feed/calendar/NzbDrone.ics?';
|
var icalUrl = window.location.host + StatusModel.get('urlBase') + '/feed/calendar/Radarr.ics?';
|
||||||
|
|
||||||
if (this.ui.includeUnmonitored.prop('checked')) {
|
if (this.ui.includeUnmonitored.prop('checked')) {
|
||||||
icalUrl += 'unmonitored=true&';
|
icalUrl += 'unmonitored=true&';
|
||||||
@@ -51,4 +51,4 @@ module.exports = Marionette.Layout.extend({
|
|||||||
this.ui.icalUrl.attr('value', icalHttpUrl);
|
this.ui.icalUrl.attr('value', icalHttpUrl);
|
||||||
this.ui.icalWebCal.attr('href', icalWebCalUrl);
|
this.ui.icalWebCal.attr('href', icalWebCalUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h3>Delete {{title}}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body delete-series-modal">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 hidden-xs">
|
||||||
|
{{poster}}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="form-horizontal">
|
||||||
|
<h3 class="path">{{path}}</h3>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Delete all files</label>
|
||||||
|
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="input-group">
|
||||||
|
<label class="checkbox toggle well">
|
||||||
|
<input type="checkbox" class="x-delete-files"/>
|
||||||
|
<p>
|
||||||
|
<span>Yes</span>
|
||||||
|
<span>No</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="btn slide-button btn-danger"/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<span class="help-inline-checkbox">
|
||||||
|
<i class="icon-sonarr-form-info" title="Do you want to delete all files from disk?"/>
|
||||||
|
<i class="icon-sonarr-form-warning" title="This option is irreversible, use with extreme caution"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-offset-1 col-md-5 delete-files-info x-delete-files-info">
|
||||||
|
{{#if hasFile}}1{{else}}0{{/if}} movie file(s) will be deleted
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<span class="indicator x-indicator"><i class="icon-sonarr-spinner fa-spin"></i></span>
|
||||||
|
<button class="btn" data-dismiss="modal">Cancel</button>
|
||||||
|
<button class="btn btn-danger x-confirm-delete">Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
var vent = require('vent');
|
||||||
|
var Marionette = require('marionette');
|
||||||
|
|
||||||
|
module.exports = Marionette.ItemView.extend({
|
||||||
|
template : 'Movies/Delete/DeleteMovieTemplate',
|
||||||
|
|
||||||
|
events : {
|
||||||
|
'click .x-confirm-delete' : 'removeSeries',
|
||||||
|
'change .x-delete-files' : 'changeDeletedFiles'
|
||||||
|
},
|
||||||
|
|
||||||
|
ui : {
|
||||||
|
deleteFiles : '.x-delete-files',
|
||||||
|
deleteFilesInfo : '.x-delete-files-info',
|
||||||
|
indicator : '.x-indicator'
|
||||||
|
},
|
||||||
|
|
||||||
|
removeSeries : function() {
|
||||||
|
var self = this;
|
||||||
|
var deleteFiles = this.ui.deleteFiles.prop('checked');
|
||||||
|
this.ui.indicator.show();
|
||||||
|
|
||||||
|
this.model.destroy({
|
||||||
|
data : { 'deleteFiles' : deleteFiles },
|
||||||
|
wait : true
|
||||||
|
}).done(function() {
|
||||||
|
vent.trigger(vent.Events.SeriesDeleted, { series : self.model });
|
||||||
|
vent.trigger(vent.Commands.CloseModalCommand);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
changeDeletedFiles : function() {
|
||||||
|
var deleteFiles = this.ui.deleteFiles.prop('checked');
|
||||||
|
|
||||||
|
if (deleteFiles) {
|
||||||
|
this.ui.deleteFilesInfo.show();
|
||||||
|
} else {
|
||||||
|
this.ui.deleteFilesInfo.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -17,7 +17,7 @@ var view = Marionette.ItemView.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
events : {
|
events : {
|
||||||
'click .x-remove' : '_removeSeries'
|
'click .x-remove' : '_removeMovie'
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize : function() {
|
initialize : function() {
|
||||||
@@ -42,8 +42,8 @@ var view = Marionette.ItemView.extend({
|
|||||||
vent.trigger(vent.Commands.CloseModalCommand);
|
vent.trigger(vent.Commands.CloseModalCommand);
|
||||||
},
|
},
|
||||||
|
|
||||||
_removeSeries : function() {
|
_removeMovie : function() {
|
||||||
vent.trigger(vent.Commands.DeleteSeriesCommand, { series : this.model });
|
vent.trigger(vent.Commands.DeleteMovieCommand, { movie : this.model });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -322,7 +322,11 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-3 control-label">Branch</label>
|
<label class="col-sm-3 control-label">Branch</label>
|
||||||
|
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-1 col-sm-push-2 help-inline">
|
||||||
|
<i class="icon-sonarr-form-warning" title="If using Docker, do not use 'develop' or 'nightly' branches"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-2 col-sm-pull-1">
|
||||||
<input type="text" placeholder="master" name="branch" class="form-control"/>
|
<input type="text" placeholder="master" name="branch" class="form-control"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<label class="col-sm-3 control-label">Preferred Tags</label>
|
<label class="col-sm-3 control-label">Preferred Tags</label>
|
||||||
|
|
||||||
<div class="col-sm-1 col-sm-push-5 help-inline">
|
<div class="col-sm-1 col-sm-push-5 help-inline">
|
||||||
<i class="icon-sonarr-form-info" title="When the release contains these tags it will be preferred." />
|
<i class="icon-sonarr-form-info" title="When the release contains these tags it will be preferred. Case Insensitive." />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-5 col-sm-pull-1">
|
<div class="col-sm-5 col-sm-pull-1">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ var AppLayout = require('../../AppLayout');
|
|||||||
var Marionette = require('marionette');
|
var Marionette = require('marionette');
|
||||||
var EditSeriesView = require('../../Series/Edit/EditSeriesView');
|
var EditSeriesView = require('../../Series/Edit/EditSeriesView');
|
||||||
var EditMovieView = require('../../Movies/Edit/EditMovieView');
|
var EditMovieView = require('../../Movies/Edit/EditMovieView');
|
||||||
var DeleteSeriesView = require('../../Series/Delete/DeleteSeriesView');
|
var DeleteMovieView = require('../../Movies/Delete/DeleteMovieView');
|
||||||
var EpisodeDetailsLayout = require('../../Episode/EpisodeDetailsLayout');
|
var EpisodeDetailsLayout = require('../../Episode/EpisodeDetailsLayout');
|
||||||
var HistoryDetailsLayout = require('../../Activity/History/Details/HistoryDetailsLayout');
|
var HistoryDetailsLayout = require('../../Activity/History/Details/HistoryDetailsLayout');
|
||||||
var LogDetailsView = require('../../System/Logs/Table/Details/LogDetailsView');
|
var LogDetailsView = require('../../System/Logs/Table/Details/LogDetailsView');
|
||||||
@@ -22,7 +22,7 @@ module.exports = Marionette.AppRouter.extend({
|
|||||||
vent.on(vent.Commands.EditSeriesCommand, this._editSeries, this);
|
vent.on(vent.Commands.EditSeriesCommand, this._editSeries, this);
|
||||||
vent.on(vent.Commands.EditMovieCommand, this._editMovie, this);
|
vent.on(vent.Commands.EditMovieCommand, this._editMovie, this);
|
||||||
vent.on(vent.Commands.EditFileCommand, this._editFile, this);
|
vent.on(vent.Commands.EditFileCommand, this._editFile, this);
|
||||||
vent.on(vent.Commands.DeleteSeriesCommand, this._deleteSeries, this);
|
vent.on(vent.Commands.DeleteMovieCommand, this._deleteMovie, this);
|
||||||
vent.on(vent.Commands.ShowEpisodeDetails, this._showEpisode, this);
|
vent.on(vent.Commands.ShowEpisodeDetails, this._showEpisode, this);
|
||||||
vent.on(vent.Commands.ShowMovieDetails, this._showMovie, this);
|
vent.on(vent.Commands.ShowMovieDetails, this._showMovie, this);
|
||||||
vent.on(vent.Commands.ShowHistoryDetails, this._showHistory, this);
|
vent.on(vent.Commands.ShowHistoryDetails, this._showHistory, this);
|
||||||
@@ -64,8 +64,8 @@ module.exports = Marionette.AppRouter.extend({
|
|||||||
AppLayout.modalRegion.show(view);
|
AppLayout.modalRegion.show(view);
|
||||||
},
|
},
|
||||||
|
|
||||||
_deleteSeries : function(options) {
|
_deleteMovie : function(options) {
|
||||||
var view = new DeleteSeriesView({ model : options.series });
|
var view = new DeleteMovieView({ model : options.movie });
|
||||||
AppLayout.modalRegion.show(view);
|
AppLayout.modalRegion.show(view);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@
|
|||||||
<meta name="msapplication-config" content="/Content/Images/favicon/browserconfig.xml">
|
<meta name="msapplication-config" content="/Content/Images/favicon/browserconfig.xml">
|
||||||
<meta name="theme-color" content="#272727">
|
<meta name="theme-color" content="#272727">
|
||||||
|
|
||||||
<link rel="alternate" type="text/calendar" title="iCalendar feed for Radarr" href="/feed/calendar/NzbDrone.ics"/>
|
<link rel="alternate" type="text/calendar" title="iCalendar feed for Radarr" href="/feed/calendar/Radarr.ics"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
+2
-1
@@ -13,8 +13,9 @@ vent.Events = {
|
|||||||
vent.Commands = {
|
vent.Commands = {
|
||||||
EditSeriesCommand : 'EditSeriesCommand',
|
EditSeriesCommand : 'EditSeriesCommand',
|
||||||
EditMovieCommand : 'EditMovieCommand',
|
EditMovieCommand : 'EditMovieCommand',
|
||||||
EditFileCommand : "EditFileCommand",
|
EditFileCommand : "EditFileCommand",
|
||||||
DeleteSeriesCommand : 'DeleteSeriesCommand',
|
DeleteSeriesCommand : 'DeleteSeriesCommand',
|
||||||
|
DeleteMovieCommand : 'DeleteMovieCommand',
|
||||||
OpenModalCommand : 'OpenModalCommand',
|
OpenModalCommand : 'OpenModalCommand',
|
||||||
CloseModalCommand : 'CloseModalCommand',
|
CloseModalCommand : 'CloseModalCommand',
|
||||||
OpenModal2Command : 'OpenModal2Command',
|
OpenModal2Command : 'OpenModal2Command',
|
||||||
|
|||||||
Reference in New Issue
Block a user