1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-02 18:57:03 -04:00

Compare commits

...

7 Commits

18 changed files with 183 additions and 51 deletions

View File

@@ -0,0 +1,26 @@
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Housekeeping.Housekeepers
{
public class CleanupOrphanedAlternativeTitles : IHousekeepingTask
{
private readonly IMainDatabase _database;
public CleanupOrphanedAlternativeTitles(IMainDatabase database)
{
_database = database;
}
public void Clean()
{
var mapper = _database.GetDataMapper();
mapper.ExecuteNonQuery(@"DELETE FROM AlternativeTitles
WHERE Id IN (
SELECT AlternativeTitles.Id FROM AlternativeTitles
LEFT OUTER JOIN Movies
ON AlternativeTitles.MovieId = Movies.Id
WHERE Movies.Id IS NULL)");
}
}
}

View File

@@ -1,11 +1,15 @@
using NzbDrone.Core.Datastore;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Movies.AlternativeTitles
{
public interface IAlternativeTitleRepository : IBasicRepository<AlternativeTitle>
{
AlternativeTitle FindBySourceId(int sourceId);
List<AlternativeTitle> FindBySourceIds(List<int> sourceIds);
}
public class AlternativeTitleRepository : BasicRepository<AlternativeTitle>, IAlternativeTitleRepository
@@ -17,5 +21,15 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
{
_database = database;
}
public AlternativeTitle FindBySourceId(int sourceId)
{
return Query.Where(t => t.SourceId == sourceId).FirstOrDefault();
}
public List<AlternativeTitle> FindBySourceIds(List<int> sourceIds)
{
return Query.Where(t => t.SourceId.In(sourceIds)).ToList();
}
}
}

View File

@@ -23,6 +23,7 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
AlternativeTitle AddAltTitle(AlternativeTitle title, Movie movie);
List<AlternativeTitle> AddAltTitles(List<AlternativeTitle> titles, Movie movie);
AlternativeTitle GetById(int id);
void DeleteNotEnoughVotes(List<AlternativeTitle> mappingsTitles);
}
public class AlternativeTitleService : IAlternativeTitleService
@@ -66,5 +67,17 @@ namespace NzbDrone.Core.Movies.AlternativeTitles
{
return _titleRepo.Get(id);
}
public void RemoveTitle(AlternativeTitle title)
{
_titleRepo.Delete(title);
}
public void DeleteNotEnoughVotes(List<AlternativeTitle> mappingsTitles)
{
var toRemove = mappingsTitles.Where(t => t.SourceType == SourceType.Mappings && t.Votes < 4);
var realT = _titleRepo.FindBySourceIds(toRemove.Select(t => t.SourceId).ToList());
_titleRepo.DeleteMany(realT);
}
}
}

View File

@@ -126,6 +126,7 @@
<Compile Include="Authentication\UserService.cs" />
<Compile Include="Datastore\Migration\123_create_netimport_table.cs" />
<Compile Include="Datastore\Migration\140_add_alternative_titles_table.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedAlternativeTitles.cs" />
<Compile Include="MediaFiles\Events\MovieFileUpdatedEvent.cs" />
<Compile Include="Datastore\Migration\134_add_remux_qualities_for_the_wankers.cs" />
<Compile Include="Datastore\Migration\129_add_parsed_movie_info_to_pending_release.cs" />

View File

@@ -121,9 +121,14 @@ namespace NzbDrone.Core.Tv
var mappingsTitles = mappings.Item1;
movie.AlternativeTitles.AddRange(_titleService.AddAltTitles(movieInfo.AlternativeTitles, movie));
_titleService.DeleteNotEnoughVotes(mappingsTitles);
mappingsTitles = mappingsTitles.ExceptBy(t => t.CleanTitle, movie.AlternativeTitles,
t => t.CleanTitle, EqualityComparer<string>.Default).ToList();
mappingsTitles = mappingsTitles.Where(t => t.Votes > 3).ToList();
movie.AlternativeTitles.AddRange(_titleService.AddAltTitles(mappingsTitles, movie));
@@ -132,11 +137,20 @@ namespace NzbDrone.Core.Tv
movie.SecondaryYear = mappings.Item2.Year;
movie.SecondaryYearSourceId = mappings.Item2.SourceId;
}
else
{
movie.SecondaryYear = null;
movie.SecondaryYearSourceId = 0;
}
}
catch (RadarrAPIException ex)
{
//Not that wild, could just be a 404.
}
catch (Exception ex)
{
_logger.Info(ex, "Unable to communicate with Mappings Server.");
}
_movieService.UpdateMovie(movie);

View File

@@ -80,6 +80,7 @@ module.exports = Marionette.Layout.extend({
var leftSideButtons = {
type : 'default',
storeState : false,
collapse: true,
items : [
{
title : 'Clear Blacklist',

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -80,3 +80,13 @@
.table-responsive {
overflow-x: visible;
}
.navbar-nav {
margin-bottom : 20px;
}
.navbar-brand {
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
padding : 22px 15px !important;
}
}

View File

@@ -6,6 +6,7 @@
src: local('Open Sans Light'),
local('OpenSans-Light'),
url('./fonts/opensans-light.eot?#iefix') format('embedded-opentype'),
url('./fonts/opensans-light.woff2') format('woff2'),
url('./fonts/opensans-light.woff') format('woff'),
url('./fonts/opensans-light.ttf') format('truetype');
}
@@ -18,6 +19,7 @@
src: local('Open Sans'),
local('OpenSans'),
url('./fonts/opensans-regular.eot?#iefix') format('embedded-opentype'),
url('./fonts/opensans-regular.woff2') format('woff2'),
url('./fonts/opensans-regular.woff') format('woff'),
url('./fonts/opensans-regular.ttf') format('truetype')
}
@@ -30,6 +32,7 @@
src: local('Open Sans SemiBold'),
local('OpenSans-SemiBold'),
url('./fonts/opensans-semibold.eot?#iefix') format('embedded-opentype'),
url('./fonts/opensans-semibold.woff2') format('woff2'),
url('./fonts/opensans-semibold.woff') format('woff'),
url('./fonts/opensans-semibold.ttf') format('truetype')
}
@@ -39,9 +42,10 @@
font-style: normal;
font-weight: 400;
src: url('./fonts/ubuntumono-regular.eot');
src: local('Open Sans'),
local('OpenSans'),
src: local('Ubuntu Mono'),
local('Ubuntu-Mono'),
url('./fonts/ubuntumono-regular.eot?#iefix') format('embedded-opentype'),
url('./fonts/ubuntumono-regular.woff2') format('woff'),
url('./fonts/ubuntumono-regular.woff') format('woff'),
url('./fonts/ubuntumono-regular.ttf') format('truetype')
}
}

View File

@@ -48,6 +48,16 @@
display : inline-block;
}
@media (max-width: @screen-sm-max) {
.x-toolbar-left-1 {
display: block;
}
.btn-group {
display: block;
}
}
.sorting-buttons {
.sorting-title {
display : inline-block;

View File

@@ -97,16 +97,17 @@ module.exports = Marionette.Layout.extend({
this.leftSideButtons = {
type : 'default',
storeState : false,
collapse: true,
items : [
{
title : 'Update Library',
title : 'Update library',
icon : 'icon-sonarr-refresh',
command : 'refreshmovie',
successMessage : 'Library was updated!',
errorMessage : 'Library update failed!'
},
{
title : 'Delete Selected',
title : 'Delete selected',
icon : 'icon-radarr-delete-white',
className: 'btn-danger',
callback : this._deleteSelected

View File

@@ -1,46 +1,81 @@
<!-- Static navbar -->
<div class="navbar navbar-nzbdrone" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle navbar-inverse" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-sonarr-navbar-collapsed fa-lg"></span>
</button>
<a class="navbar-brand" href="{{UrlBase}}/">
<!--<img src="{{UrlBase}}/Content/Images/logo.png?v=2" alt="Radarr">-->
<img src="{{UrlBase}}/Content/Images/logos/128.png" class="visible-lg"/>
<img src="{{UrlBase}}/Content/Images/logos/64.png" class="visible-md visible-sm"/>
<span class="visible-xs">
<img src="{{UrlBase}}/Content/Images/logos/32.png"/>
<span class="logo-text">Radarr</span>
</span>
</a>
</div>
<div class="navbar-collapse collapse x-navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="{{UrlBase}}/addmovies" class="x-series-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-add"></i> Add Movies</a></li>
<li><a href="{{UrlBase}}/" class="x-series-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-series"></i> Movies</a></li>
<li><a href="{{UrlBase}}/calendar" class="x-calendar-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-calendar"></i> Calendar</a></li>
<li><a href="{{UrlBase}}/activity" class="x-activity-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-activity"></i> Activity<span id="x-queue-count" class="navbar-info"></span></a></li>
<li><a href="{{UrlBase}}/wanted" class="x-wanted-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-wanted"></i> Wanted</a></li>
<li><a href="{{UrlBase}}/settings" class="x-settings-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-settings"></i> Settings</a></li>
<li><a href="{{UrlBase}}/system" class="x-system-nav"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-system"></i> System<span id="x-health" class="navbar-info"></span></a></li>
<li><a href="https://radarr.video/donate.html" target="_blank"><i class="icon-sonarr-navbar-icon icon-sonarr-navbar-donate"></i> Donate</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="active screen-size"></li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
<div class="col-md-12 search">
<div class="col-md-6 col-md-offset-3">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
<input type="text" class="col-md-6 form-control x-series-search" placeholder="Search the movies in your library">
</div>
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle navbar-inverse" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-sonarr-navbar-collapsed fa-lg"></span>
</button>
<a class="navbar-brand" href="{{UrlBase}}/">
<img src="{{UrlBase}}/Content/Images/logos/128.png" class="visible-md visible-lg">
<img src="{{UrlBase}}/Content/Images/logos/64.png" class="visible-sm">
<div class="visible-xs">
<img src="{{UrlBase}}/Content/Images/logos/32.png"/>
<span class="logo-text">Radarr</span>
</div>
</a>
</div>
<div class="navbar-collapse collapse x-navbar-collapse">
<ul class="nav navbar-nav">
<li>
<a href="{{UrlBase}}/addmovies" class="x-series-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-add" aria-hidden="true"></i>
Add Movies
</a>
</li>
<li>
<a href="{{UrlBase}}/" class="x-series-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-series" aria-hidden="true"></i>
Movies
</a>
</li>
<li>
<a href="{{UrlBase}}/calendar" class="x-calendar-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-calendar" aria-hidden="true"></i>
Calendar
</a>
</li>
<li>
<a href="{{UrlBase}}/activity" class="x-activity-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-activity" aria-hidden="true"></i>
Activity <span id="x-queue-count" class="navbar-info"></span>
</a>
</li>
<li>
<a href="{{UrlBase}}/wanted" class="x-wanted-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-wanted" aria-hidden="true"></i>
Wanted
</a>
</li>
<li>
<a href="{{UrlBase}}/settings" class="x-settings-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-settings" aria-hidden="true"></i>
Settings
</a>
</li>
<li>
<a href="{{UrlBase}}/system" class="x-system-nav">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-system" aria-hidden="true"></i>
System <span id="x-health" class="navbar-info"></span>
</a>
</li>
<li>
<a href="https://radarr.video/donate.html" target="_blank">
<i class="icon-sonarr-navbar-icon icon-sonarr-navbar-donate" aria-hidden="true"></i>
Donate
</a>
</li>
</ul>
</div>
</div>
<div class="col-md-12 search">
<div class="col-md-6 col-md-offset-3">
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-search"></i>
</span>
<input type="text" class="col-md-6 form-control x-series-search" placeholder="Search the movies in your library">
</div>
</div>
</div>
</div>

View File

@@ -41,7 +41,7 @@ module.exports = Marionette.Layout.extend({
leftSideButtons : {
type : 'default',
storeState : false,
collapse : false,
collapse : true,
items : [
{
title : 'Backup',

View File

@@ -97,6 +97,7 @@ module.exports = Marionette.Layout.extend({
var leftSideButtons = {
type : 'default',
storeState : false,
collapse: true,
items : [
{
title : 'Search Selected',

View File

@@ -88,8 +88,8 @@
</div>
<div id="control-panel-region" class="control-panel"></div>
<div id="errors"></div>
</body>
<script type="text/javascript">
<script>
window.NzbDrone = {
ApiRoot : 'API_ROOT',
ApiKey : 'API_KEY',
@@ -106,4 +106,6 @@
<script src="/templates.js"></script>
<script src="/vendor.js"></script>
<script src="/main.js"></script>
</body>
</html>