Merge branch 'develop' into rename-existing-folder

pull/489/head
Tim Turner 8 years ago
commit 4bcb0e17f8

@ -11,6 +11,7 @@ namespace NzbDrone.Api.Profiles
{ {
public string Name { get; set; } public string Name { get; set; }
public Quality Cutoff { get; set; } public Quality Cutoff { get; set; }
public string PreferredTags { get; set; }
public List<ProfileQualityItemResource> Items { get; set; } public List<ProfileQualityItemResource> Items { get; set; }
public Language Language { get; set; } public Language Language { get; set; }
} }
@ -33,6 +34,7 @@ namespace NzbDrone.Api.Profiles
Name = model.Name, Name = model.Name,
Cutoff = model.Cutoff, Cutoff = model.Cutoff,
PreferredTags = model.PreferredTags != null ? string.Join(",", model.PreferredTags) : "",
Items = model.Items.ConvertAll(ToResource), Items = model.Items.ConvertAll(ToResource),
Language = model.Language Language = model.Language
}; };
@ -59,6 +61,7 @@ namespace NzbDrone.Api.Profiles
Name = resource.Name, Name = resource.Name,
Cutoff = (Quality)resource.Cutoff.Id, Cutoff = (Quality)resource.Cutoff.Id,
PreferredTags = resource.PreferredTags.Split(',').ToList(),
Items = resource.Items.ConvertAll(ToModel), Items = resource.Items.ConvertAll(ToModel),
Language = resource.Language Language = resource.Language
}; };

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
using System.Data;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(124)]
public class add_preferred_tags_to_profile : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Profiles").AddColumn("PreferredTags").AsString().Nullable();
}
}
}

@ -23,6 +23,7 @@ namespace NzbDrone.Core.DecisionEngine
var comparers = new List<CompareDelegate> var comparers = new List<CompareDelegate>
{ {
CompareQuality, CompareQuality,
ComparePreferredWords,
CompareProtocol, CompareProtocol,
ComparePeersIfTorrent, ComparePeersIfTorrent,
CompareAgeIfUsenet, CompareAgeIfUsenet,
@ -65,6 +66,26 @@ namespace NzbDrone.Core.DecisionEngine
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version)); CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
} }
private int ComparePreferredWords(DownloadDecision x, DownloadDecision y)
{
return CompareBy(x.RemoteMovie, y.RemoteMovie, remoteMovie =>
{
var title = remoteMovie.Release.Title;
remoteMovie.Movie.Profile.LazyLoad();
var preferredWords = remoteMovie.Movie.Profile.Value.PreferredTags;
if (preferredWords == null)
{
return 0;
}
var num = preferredWords.AsEnumerable().Count(w => title.ToLower().Contains(w.ToLower()));
return num;
});
; }
private int CompareProtocol(DownloadDecision x, DownloadDecision y) private int CompareProtocol(DownloadDecision x, DownloadDecision y)
{ {

@ -56,6 +56,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
environmentVariables.Add("Radarr_EventType", "Download"); environmentVariables.Add("Radarr_EventType", "Download");
environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString()); environmentVariables.Add("Radarr_Movie_Id", movie.Id.ToString());
environmentVariables.Add("Radarr_Movie_Title", movie.Title); environmentVariables.Add("Radarr_Movie_Title", movie.Title);
environmentVariables.Add("Radarr_Movie_Path", movie.Path);
environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId.ToString()); environmentVariables.Add("Radarr_Movie_ImdbId", movie.ImdbId.ToString());
environmentVariables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString()); environmentVariables.Add("Radarr_MovieFile_Id", movieFile.Id.ToString());
environmentVariables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath); environmentVariables.Add("Radarr_MovieFile_RelativePath", movieFile.RelativePath);

@ -37,14 +37,18 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
if (Settings.UpdateLibrary) if (Settings.UpdateLibrary)
{ {
_mediaBrowserService.Update(Settings, message.Series); _mediaBrowserService.UpdateMovies(Settings, message.Movie);
} }
} }
public override void OnMovieRename(Movie movie) public override void OnMovieRename(Movie movie)
{ {
if (Settings.UpdateLibrary)
{
_mediaBrowserService.UpdateMovies(Settings, movie);
}
} }
public override void OnRename(Series series) public override void OnRename(Series series)
{ {
if (Settings.UpdateLibrary) if (Settings.UpdateLibrary)

@ -40,6 +40,16 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
ProcessRequest(request, settings); ProcessRequest(request, settings);
} }
public void UpdateMovies(MediaBrowserSettings settings, string imdbid)
{
var path = string.Format("/Library/Movies/Updated?ImdbId={0}", imdbid);
var request = BuildRequest(path, settings);
request.Headers.Add("Content-Length", "0");
ProcessRequest(request, settings);
}
private string ProcessRequest(HttpRequest request, MediaBrowserSettings settings) private string ProcessRequest(HttpRequest request, MediaBrowserSettings settings)
{ {
request.Headers.Add("X-MediaBrowser-Token", settings.ApiKey); request.Headers.Add("X-MediaBrowser-Token", settings.ApiKey);

@ -11,6 +11,7 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
{ {
void Notify(MediaBrowserSettings settings, string title, string message); void Notify(MediaBrowserSettings settings, string title, string message);
void Update(MediaBrowserSettings settings, Series series); void Update(MediaBrowserSettings settings, Series series);
void UpdateMovies(MediaBrowserSettings settings, Movie movie);
ValidationFailure Test(MediaBrowserSettings settings); ValidationFailure Test(MediaBrowserSettings settings);
} }
@ -35,6 +36,13 @@ namespace NzbDrone.Core.Notifications.MediaBrowser
_proxy.Update(settings, series.TvdbId); _proxy.Update(settings, series.TvdbId);
} }
public void UpdateMovies(MediaBrowserSettings settings, Movie movie)
{
_proxy.UpdateMovies(settings, movie.ImdbId);
}
public ValidationFailure Test(MediaBrowserSettings settings) public ValidationFailure Test(MediaBrowserSettings settings)
{ {
try try

@ -51,6 +51,24 @@ namespace NzbDrone.Core.Notifications.Xbmc
UpdateLibrary(settings, series); UpdateLibrary(settings, series);
} }
public void UpdateMovie(XbmcSettings settings, Movie movie)
{
if (!settings.AlwaysUpdate)
{
_logger.Debug("Determining if there are any active players on XBMC host: {0}", settings.Address);
var activePlayers = GetActivePlayers(settings);
if (activePlayers.Any(a => a.Type.Equals("video")))
{
_logger.Debug("Video is currently playing, skipping library update");
return;
}
}
UpdateMovieLibrary(settings, movie);
}
public void Clean(XbmcSettings settings) public void Clean(XbmcSettings settings)
{ {
const string cleanVideoLibrary = "CleanLibrary(video)"; const string cleanVideoLibrary = "CleanLibrary(video)";
@ -167,6 +185,37 @@ namespace NzbDrone.Core.Notifications.Xbmc
} }
} }
private void UpdateMovieLibrary(XbmcSettings settings, Movie movie)
{
try
{
//_logger.Debug("Sending Update DB Request to XBMC Host: {0}", settings.Address);
//var xbmcSeriesPath = GetSeriesPath(settings, series);
////If the path is found update it, else update the whole library
//if (!string.IsNullOrEmpty(xbmcSeriesPath))
//{
// _logger.Debug("Updating series [{0}] on XBMC host: {1}", series, settings.Address);
// var command = BuildExecBuiltInCommand(string.Format("UpdateLibrary(video,{0})", xbmcSeriesPath));
// SendCommand(settings, command);
//}
//else
//{
//Update the entire library
_logger.Debug("Series [{0}] doesn't exist on XBMC host: {1}, Updating Entire Library", movie, settings.Address);
var command = BuildExecBuiltInCommand("UpdateLibrary(video)");
SendCommand(settings, command);
//}
}
catch (Exception ex)
{
_logger.Debug(ex, ex.Message);
}
}
private string SendCommand(XbmcSettings settings, string command) private string SendCommand(XbmcSettings settings, string command)
{ {
var url = string.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", settings.Address, command); var url = string.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", settings.Address, command);

@ -7,6 +7,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
{ {
void Notify(XbmcSettings settings, string title, string message); void Notify(XbmcSettings settings, string title, string message);
void Update(XbmcSettings settings, Series series); void Update(XbmcSettings settings, Series series);
void UpdateMovie(XbmcSettings settings, Movie movie);
void Clean(XbmcSettings settings); void Clean(XbmcSettings settings);
bool CanHandle(XbmcVersion version); bool CanHandle(XbmcVersion version);
} }

@ -44,7 +44,25 @@ namespace NzbDrone.Core.Notifications.Xbmc
UpdateLibrary(settings, series); UpdateLibrary(settings, series);
} }
public void UpdateMovie(XbmcSettings settings, Movie movie)
{
if (!settings.AlwaysUpdate)
{
_logger.Debug("Determining if there are any active players on XBMC host: {0}", settings.Address);
var activePlayers = _proxy.GetActivePlayers(settings);
if (activePlayers.Any(a => a.Type.Equals("video")))
{
_logger.Debug("Video is currently playing, skipping library update");
return;
}
}
UpdateMovieLibrary(settings, movie);
}
public void Clean(XbmcSettings settings) public void Clean(XbmcSettings settings)
{ {
_proxy.CleanLibrary(settings); _proxy.CleanLibrary(settings);
@ -108,5 +126,23 @@ namespace NzbDrone.Core.Notifications.Xbmc
_logger.Debug(ex, ex.Message); _logger.Debug(ex, ex.Message);
} }
} }
private void UpdateMovieLibrary(XbmcSettings settings, Movie movie)
{
try
{
var response = _proxy.UpdateLibrary(settings, null);
if (!response.Equals("OK", StringComparison.InvariantCultureIgnoreCase))
{
_logger.Debug("Failed to update library for: {0}", settings.Address);
}
}
catch (Exception ex)
{
_logger.Debug(ex, ex.Message);
}
}
} }
} }

@ -33,13 +33,14 @@ namespace NzbDrone.Core.Notifications.Xbmc
const string header = "Radarr - Downloaded"; const string header = "Radarr - Downloaded";
Notify(Settings, header, message.Message); Notify(Settings, header, message.Message);
UpdateAndClean(message.Series, message.OldFiles.Any()); UpdateAndCleanMovie(message.Movie, message.OldMovieFiles.Any());
} }
public override void OnMovieRename(Movie movie) public override void OnMovieRename(Movie movie)
{ {
UpdateAndCleanMovie(movie);
} }
public override void OnRename(Series series) public override void OnRename(Series series)
{ {
UpdateAndClean(series); UpdateAndClean(series);
@ -92,5 +93,26 @@ namespace NzbDrone.Core.Notifications.Xbmc
_logger.Debug(ex, logMessage); _logger.Debug(ex, logMessage);
} }
} }
private void UpdateAndCleanMovie(Movie movie, bool clean = true)
{
try
{
if (Settings.UpdateLibrary)
{
_xbmcService.UpdateMovie(Settings, movie);
}
if (clean && Settings.CleanLibrary)
{
_xbmcService.Clean(Settings);
}
}
catch (SocketException ex)
{
var logMessage = string.Format("Unable to connect to XBMC Host: {0}:{1}", Settings.Host, Settings.Port);
_logger.Debug(ex, logMessage);
}
}
} }
} }

@ -15,6 +15,7 @@ namespace NzbDrone.Core.Notifications.Xbmc
{ {
void Notify(XbmcSettings settings, string title, string message); void Notify(XbmcSettings settings, string title, string message);
void Update(XbmcSettings settings, Series series); void Update(XbmcSettings settings, Series series);
void UpdateMovie(XbmcSettings settings, Movie movie);
void Clean(XbmcSettings settings); void Clean(XbmcSettings settings);
ValidationFailure Test(XbmcSettings settings, string message); ValidationFailure Test(XbmcSettings settings, string message);
} }
@ -51,6 +52,12 @@ namespace NzbDrone.Core.Notifications.Xbmc
provider.Update(settings, series); provider.Update(settings, series);
} }
public void UpdateMovie(XbmcSettings settings, Movie movie)
{
var provider = GetApiProvider(settings);
provider.UpdateMovie(settings, movie);
}
public void Clean(XbmcSettings settings) public void Clean(XbmcSettings settings)
{ {
var provider = GetApiProvider(settings); var provider = GetApiProvider(settings);

@ -183,6 +183,7 @@
<Compile Include="Datastore\Migration\002_remove_tvrage_imdb_unique_constraint.cs" /> <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\003_remove_clean_title_from_scene_mapping.cs" />
<Compile Include="Datastore\Migration\004_updated_history.cs" /> <Compile Include="Datastore\Migration\004_updated_history.cs" />
<Compile Include="Datastore\Migration\124_add_preferred_tags_to_profile.cs" />
<Compile Include="Datastore\Migration\122_add_movieid_to_blacklist.cs" /> <Compile Include="Datastore\Migration\122_add_movieid_to_blacklist.cs" />
<Compile Include="Datastore\Migration\121_update_filedate_config.cs" /> <Compile Include="Datastore\Migration\121_update_filedate_config.cs" />
<Compile Include="Datastore\Migration\120_add_studio_to_table.cs" /> <Compile Include="Datastore\Migration\120_add_studio_to_table.cs" />

@ -11,6 +11,7 @@ namespace NzbDrone.Core.Profiles
public string Name { get; set; } public string Name { get; set; }
public Quality Cutoff { get; set; } public Quality Cutoff { get; set; }
public List<ProfileQualityItem> Items { get; set; } public List<ProfileQualityItem> Items { get; set; }
public List<string> PreferredTags { get; set; }
public Language Language { get; set; } public Language Language { get; set; }
public Quality LastAllowedQuality() public Quality LastAllowedQuality()

@ -4,25 +4,37 @@ var LanguageCollection = require('../Language/LanguageCollection');
var Config = require('../../../Config'); var Config = require('../../../Config');
var AsModelBoundView = require('../../../Mixins/AsModelBoundView'); var AsModelBoundView = require('../../../Mixins/AsModelBoundView');
var AsValidatedView = require('../../../Mixins/AsValidatedView'); var AsValidatedView = require('../../../Mixins/AsValidatedView');
require('../../../Mixins/TagInput');
require('bootstrap');
require('bootstrap.tagsinput');
var view = Marionette.ItemView.extend({ var view = Marionette.ItemView.extend({
template : 'Settings/Profile/Edit/EditProfileViewTemplate', template : 'Settings/Profile/Edit/EditProfileViewTemplate',
ui : { cutoff : '.x-cutoff' }, ui : { cutoff : '.x-cutoff',
preferred : '.x-preferred',
},
templateHelpers : function() { onRender : function() {
return { this.ui.preferred.tagsinput({
languages : LanguageCollection.toJSON() trimValue : true,
}; tagClass : 'label label-success'
}, });
},
getCutoff : function() { templateHelpers : function() {
var self = this; return {
languages : LanguageCollection.toJSON()
};
},
return _.findWhere(_.pluck(this.model.get('items'), 'quality'), { id : parseInt(self.ui.cutoff.val(), 10) }); getCutoff : function() {
} var self = this;
return _.findWhere(_.pluck(this.model.get('items'), 'quality'), { id : parseInt(self.ui.cutoff.val(), 10) });
}
}); });
AsValidatedView.call(view); AsValidatedView.call(view);
module.exports = AsModelBoundView.call(view); module.exports = AsModelBoundView.call(view);

@ -1,45 +1,59 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">Name</label> <label class="col-sm-3 control-label">Name</label>
<div class="col-sm-5"> <div class="col-sm-5">
<input type="text" name="name" class="form-control"> <input type="text" name="name" class="form-control">
</div> </div>
</div> </div>
<hr> <hr>
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">Language</label> <label class="col-sm-3 control-label">Language</label>
<div class="col-sm-5"> <div class="col-sm-5">
<select class="form-control" name="language"> <select class="form-control" name="language">
{{#each languages}} {{#each languages}}
{{#unless_eq nameLower compare="unknown"}} {{#unless_eq nameLower compare="unknown"}}
<option value="{{nameLower}}">{{name}}</option> <option value="{{nameLower}}">{{name}}</option>
{{/unless_eq}} {{/unless_eq}}
{{/each}} {{/each}}
</select> </select>
</div> </div>
<div class="col-sm-1 help-inline"> <div class="col-sm-1 help-inline">
<i class="icon-sonarr-form-info" title="Series assigned this profile will be look for episodes with the selected language"/> <i class="icon-sonarr-form-info" title="Series assigned this profile will be look for episodes with the selected language"/>
</div> </div>
</div> </div>
<div class="form-group">
<label class="col-sm-3 control-label">Preferred Tags</label>
<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." />
</div>
<div class="col-sm-5 col-sm-pull-1">
<input type="text" name="preferredTags" class="form-control x-preferred"/>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">Cutoff</label> <label class="col-sm-3 control-label">Cutoff</label>
<div class="col-sm-5"> <div class="col-sm-5">
<select class="form-control x-cutoff" name="cutoff.id" validation-name="cutoff"> <select class="form-control x-cutoff" name="cutoff.id" validation-name="cutoff">
{{#eachReverse items}} {{#eachReverse items}}
{{#if allowed}} {{#if allowed}}
<option value="{{quality.id}}">{{quality.name}}</option> <option value="{{quality.id}}">{{quality.name}}</option>
{{/if}} {{/if}}
{{/eachReverse}} {{/eachReverse}}
</select> </select>
</div> </div>
<div class="col-sm-1 help-inline"> <div class="col-sm-1 help-inline">
<i class="icon-sonarr-form-info" title="Once this quality is reached Radarr will no longer download episodes"/> <i class="icon-sonarr-form-info" title="Once this quality is reached Radarr will no longer download episodes"/>
</div> </div>
</div> </div>

@ -6,30 +6,32 @@ require('./AllowedLabeler');
require('./LanguageLabel'); require('./LanguageLabel');
require('bootstrap'); require('bootstrap');
var view = Marionette.ItemView.extend({ var view = Marionette.ItemView.extend({
template : 'Settings/Profile/ProfileViewTemplate', template : 'Settings/Profile/ProfileViewTemplate',
tagName : 'li', tagName : 'li',
ui : { ui : {
"progressbar" : '.progress .bar', "progressbar" : '.progress .bar',
"deleteButton" : '.x-delete' "deleteButton" : '.x-delete',
},
},
events : {
'click' : '_editProfile' events : {
}, 'click' : '_editProfile'
},
initialize : function() {
this.listenTo(this.model, 'sync', this.render); initialize : function() {
}, this.listenTo(this.model, 'sync', this.render);
},
_editProfile : function() {
var view = new EditProfileView({ _editProfile : function() {
model : this.model, var view = new EditProfileView({
profileCollection : this.model.collection model : this.model,
}); profileCollection : this.model.collection
AppLayout.modalRegion.show(view); });
} AppLayout.modalRegion.show(view);
}
}); });
module.exports = AsModelBoundView.call(view); module.exports = AsModelBoundView.call(view);

@ -1,13 +1,13 @@
<div class="profile-item thingy"> <div class="profile-item thingy">
<div> <div>
<h3 name="name"></h3> <h3 name="name"></h3>
</div> </div>
<div class="language"> <div class="language">
{{languageLabel}} {{languageLabel}}
</div> </div>
<ul class="allowed-qualities"> <ul class="allowed-qualities">
{{allowedLabeler}} {{allowedLabeler}}
</ul> </ul>
</div> </div>

Loading…
Cancel
Save