mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-17 15:02:34 +02:00
New: Aphrodite Language Improvements
This commit is contained in:
parent
965ed041ae
commit
10322a1867
@ -6,7 +6,7 @@ function MovieAlternateTitles({ alternateTitles }) {
|
|||||||
return (
|
return (
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{
|
||||||
alternateTitles.map((alternateTitle) => {
|
alternateTitles.filter((x, i, a) => a.indexOf(x) === i).map((alternateTitle) => {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
key={alternateTitle}
|
key={alternateTitle}
|
||||||
|
@ -243,7 +243,7 @@ class MovieDetails extends Component {
|
|||||||
collection,
|
collection,
|
||||||
overview,
|
overview,
|
||||||
youTubeTrailerId,
|
youTubeTrailerId,
|
||||||
inCinemas,
|
isAvailable,
|
||||||
images,
|
images,
|
||||||
tags,
|
tags,
|
||||||
isSaving,
|
isSaving,
|
||||||
@ -483,7 +483,7 @@ class MovieDetails extends Component {
|
|||||||
<MovieStatusLabel
|
<MovieStatusLabel
|
||||||
hasMovieFiles={hasMovieFiles}
|
hasMovieFiles={hasMovieFiles}
|
||||||
monitored={monitored}
|
monitored={monitored}
|
||||||
inCinemas={inCinemas}
|
isAvailable={isAvailable}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</InfoLabel>
|
</InfoLabel>
|
||||||
@ -722,6 +722,7 @@ MovieDetails.propTypes = {
|
|||||||
studio: PropTypes.string,
|
studio: PropTypes.string,
|
||||||
collection: PropTypes.object,
|
collection: PropTypes.object,
|
||||||
youTubeTrailerId: PropTypes.string,
|
youTubeTrailerId: PropTypes.string,
|
||||||
|
isAvailable: PropTypes.bool.isRequired,
|
||||||
inCinemas: PropTypes.string,
|
inCinemas: PropTypes.string,
|
||||||
overview: PropTypes.string.isRequired,
|
overview: PropTypes.string.isRequired,
|
||||||
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
images: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import moment from 'moment';
|
|
||||||
import styles from './MovieStatusLabel.css';
|
import styles from './MovieStatusLabel.css';
|
||||||
|
|
||||||
function getMovieStatus(hasFile, isMonitored, inCinemas) {
|
function getMovieStatus(hasFile, isMonitored, isAvailable) {
|
||||||
const currentTime = moment();
|
|
||||||
|
|
||||||
if (hasFile) {
|
if (hasFile) {
|
||||||
return 'Downloaded';
|
return 'Downloaded';
|
||||||
@ -14,7 +12,7 @@ function getMovieStatus(hasFile, isMonitored, inCinemas) {
|
|||||||
return 'Unmonitored';
|
return 'Unmonitored';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inCinemas.isBefore(currentTime) && !hasFile) {
|
if (isAvailable && !hasFile) {
|
||||||
return 'Missing';
|
return 'Missing';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,10 +23,10 @@ function MovieStatusLabel(props) {
|
|||||||
const {
|
const {
|
||||||
hasMovieFiles,
|
hasMovieFiles,
|
||||||
monitored,
|
monitored,
|
||||||
inCinemas
|
isAvailable
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const status = getMovieStatus(hasMovieFiles, monitored, moment(inCinemas));
|
const status = getMovieStatus(hasMovieFiles, monitored, isAvailable);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
@ -42,7 +40,7 @@ function MovieStatusLabel(props) {
|
|||||||
MovieStatusLabel.propTypes = {
|
MovieStatusLabel.propTypes = {
|
||||||
hasMovieFiles: PropTypes.bool.isRequired,
|
hasMovieFiles: PropTypes.bool.isRequired,
|
||||||
monitored: PropTypes.bool.isRequired,
|
monitored: PropTypes.bool.isRequired,
|
||||||
inCinemas: PropTypes.string
|
isAvailable: PropTypes.bool.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
MovieStatusLabel.defaultProps = {
|
MovieStatusLabel.defaultProps = {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import MovieLanguage from 'Movie/MovieLanguage';
|
import MovieLanguage from 'Movie/MovieLanguage';
|
||||||
@ -12,7 +13,8 @@ class MovieTitlesRow extends Component {
|
|||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
title,
|
title,
|
||||||
language
|
language,
|
||||||
|
sourceType
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// TODO - Fix languages to all take arrays
|
// TODO - Fix languages to all take arrays
|
||||||
@ -31,6 +33,10 @@ class MovieTitlesRow extends Component {
|
|||||||
/>
|
/>
|
||||||
</TableRowCell>
|
</TableRowCell>
|
||||||
|
|
||||||
|
<TableRowCell>
|
||||||
|
{titleCase(sourceType)}
|
||||||
|
</TableRowCell>
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -39,7 +45,8 @@ class MovieTitlesRow extends Component {
|
|||||||
MovieTitlesRow.propTypes = {
|
MovieTitlesRow.propTypes = {
|
||||||
id: PropTypes.number.isRequired,
|
id: PropTypes.number.isRequired,
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
language: PropTypes.object.isRequired
|
language: PropTypes.object.isRequired,
|
||||||
|
sourceType: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MovieTitlesRow;
|
export default MovieTitlesRow;
|
||||||
|
@ -16,6 +16,11 @@ const columns = [
|
|||||||
name: 'language',
|
name: 'language',
|
||||||
label: 'Language',
|
label: 'Language',
|
||||||
isVisible: true
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sourceType',
|
||||||
|
label: 'Type',
|
||||||
|
isVisible: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -18,11 +18,14 @@ function createMapStateToProps() {
|
|||||||
items
|
items
|
||||||
} = languages;
|
} = languages;
|
||||||
|
|
||||||
|
const filterItems = ['Any', 'Unknown'];
|
||||||
|
const filteredLanguages = items.filter((lang) => !filterItems.includes(lang.name));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isFetching,
|
isFetching,
|
||||||
isPopulated,
|
isPopulated,
|
||||||
error,
|
error,
|
||||||
items
|
items: filteredLanguages
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -55,6 +55,7 @@ class UISettings extends Component {
|
|||||||
hasSettings,
|
hasSettings,
|
||||||
onInputChange,
|
onInputChange,
|
||||||
onSavePress,
|
onSavePress,
|
||||||
|
languages,
|
||||||
...otherProps
|
...otherProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -174,6 +175,22 @@ class UISettings extends Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FieldSet>
|
</FieldSet>
|
||||||
|
|
||||||
|
<FieldSet
|
||||||
|
legend="Language"
|
||||||
|
>
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>Movie Info Language</FormLabel>
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.SELECT}
|
||||||
|
name="movieInfoLanguage"
|
||||||
|
values={languages}
|
||||||
|
helpText="Language that Radarr will use to display Movie Title in UI"
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...settings.movieInfoLanguage}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FieldSet>
|
||||||
</Form>
|
</Form>
|
||||||
}
|
}
|
||||||
</PageContentBody>
|
</PageContentBody>
|
||||||
@ -189,6 +206,7 @@ UISettings.propTypes = {
|
|||||||
settings: PropTypes.object.isRequired,
|
settings: PropTypes.object.isRequired,
|
||||||
hasSettings: PropTypes.bool.isRequired,
|
hasSettings: PropTypes.bool.isRequired,
|
||||||
onSavePress: PropTypes.func.isRequired,
|
onSavePress: PropTypes.func.isRequired,
|
||||||
|
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
onInputChange: PropTypes.func.isRequired
|
onInputChange: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,13 +9,38 @@ import UISettings from './UISettings';
|
|||||||
|
|
||||||
const SECTION = 'ui';
|
const SECTION = 'ui';
|
||||||
|
|
||||||
|
function createLanguagesSelector() {
|
||||||
|
return createSelector(
|
||||||
|
(state) => state.settings.languages,
|
||||||
|
(languages) => {
|
||||||
|
const items = languages.items;
|
||||||
|
const filterItems = ['Any', 'Unknown'];
|
||||||
|
|
||||||
|
if (!items) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const newItems = items.filter((lang) => !filterItems.includes(lang.name)).map((item) => {
|
||||||
|
return {
|
||||||
|
key: item.id,
|
||||||
|
value: item.name
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return newItems;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
return createSelector(
|
return createSelector(
|
||||||
(state) => state.settings.advancedSettings,
|
(state) => state.settings.advancedSettings,
|
||||||
createSettingsSectionSelector(SECTION),
|
createSettingsSectionSelector(SECTION),
|
||||||
(advancedSettings, sectionSettings) => {
|
createLanguagesSelector(),
|
||||||
|
(advancedSettings, sectionSettings, languages) => {
|
||||||
return {
|
return {
|
||||||
advancedSettings,
|
advancedSettings,
|
||||||
|
languages,
|
||||||
...sectionSettings
|
...sectionSettings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,7 @@ private void CreateEvent(Ical.Net.Calendar calendar, Movie movie, bool cinemasRe
|
|||||||
occurrence.Description = movie.Overview;
|
occurrence.Description = movie.Overview;
|
||||||
occurrence.Categories = new List<string>() { movie.Studio };
|
occurrence.Categories = new List<string>() { movie.Studio };
|
||||||
|
|
||||||
var physicalText = movie.PhysicalReleaseNote.IsNotNullOrWhiteSpace()
|
var physicalText = "(Physical Release)";
|
||||||
? $"(Physical Release, {movie.PhysicalReleaseNote})"
|
|
||||||
: "(Physical Release)";
|
|
||||||
occurrence.Summary = $"{movie.Title} " + (cinemasRelease ? "(Theatrical Release)" : physicalText);
|
occurrence.Summary = $"{movie.Title} " + (cinemasRelease ? "(Theatrical Release)" : physicalText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public static NamingConfigResource ToResource(this NamingConfig model)
|
|||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
|
|
||||||
RenameEpisodes = model.RenameEpisodes,
|
RenameEpisodes = model.RenameMovies,
|
||||||
ReplaceIllegalCharacters = model.ReplaceIllegalCharacters,
|
ReplaceIllegalCharacters = model.ReplaceIllegalCharacters,
|
||||||
ColonReplacementFormat = model.ColonReplacementFormat,
|
ColonReplacementFormat = model.ColonReplacementFormat,
|
||||||
MultiEpisodeStyle = model.MultiEpisodeStyle,
|
MultiEpisodeStyle = model.MultiEpisodeStyle,
|
||||||
@ -59,7 +59,7 @@ public static NamingConfig ToModel(this NamingConfigResource resource)
|
|||||||
{
|
{
|
||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
|
|
||||||
RenameEpisodes = resource.RenameEpisodes,
|
RenameMovies = resource.RenameEpisodes,
|
||||||
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
||||||
ColonReplacementFormat = resource.ColonReplacementFormat,
|
ColonReplacementFormat = resource.ColonReplacementFormat,
|
||||||
StandardMovieFormat = resource.StandardMovieFormat,
|
StandardMovieFormat = resource.StandardMovieFormat,
|
||||||
|
@ -122,7 +122,6 @@ public static MovieResource ToResource(this Core.Movies.Movie model)
|
|||||||
SortTitle = model.SortTitle,
|
SortTitle = model.SortTitle,
|
||||||
InCinemas = model.InCinemas,
|
InCinemas = model.InCinemas,
|
||||||
PhysicalRelease = model.PhysicalRelease,
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
PhysicalReleaseNote = model.PhysicalReleaseNote,
|
|
||||||
HasFile = model.HasFile,
|
HasFile = model.HasFile,
|
||||||
Downloaded = downloaded,
|
Downloaded = downloaded,
|
||||||
|
|
||||||
@ -139,7 +138,6 @@ public static MovieResource ToResource(this Core.Movies.Movie model)
|
|||||||
|
|
||||||
Year = model.Year,
|
Year = model.Year,
|
||||||
SecondaryYear = model.SecondaryYear,
|
SecondaryYear = model.SecondaryYear,
|
||||||
SecondaryYearSourceId = model.SecondaryYearSourceId,
|
|
||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
ProfileId = model.ProfileId,
|
ProfileId = model.ProfileId,
|
||||||
@ -189,7 +187,6 @@ public static Core.Movies.Movie ToModel(this MovieResource resource)
|
|||||||
SortTitle = resource.SortTitle,
|
SortTitle = resource.SortTitle,
|
||||||
InCinemas = resource.InCinemas,
|
InCinemas = resource.InCinemas,
|
||||||
PhysicalRelease = resource.PhysicalRelease,
|
PhysicalRelease = resource.PhysicalRelease,
|
||||||
PhysicalReleaseNote = resource.PhysicalReleaseNote,
|
|
||||||
|
|
||||||
//TotalEpisodeCount
|
//TotalEpisodeCount
|
||||||
//EpisodeCount
|
//EpisodeCount
|
||||||
@ -203,7 +200,6 @@ public static Core.Movies.Movie ToModel(this MovieResource resource)
|
|||||||
|
|
||||||
Year = resource.Year,
|
Year = resource.Year,
|
||||||
SecondaryYear = resource.SecondaryYear,
|
SecondaryYear = resource.SecondaryYear,
|
||||||
SecondaryYearSourceId = resource.SecondaryYearSourceId,
|
|
||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.ProfileId,
|
ProfileId = resource.ProfileId,
|
||||||
|
@ -31,7 +31,7 @@ public void should_delete_extra_files_that_dont_have_a_coresponding_movie()
|
|||||||
public void should_not_delete_extra_files_that_have_a_coresponding_movie()
|
public void should_not_delete_extra_files_that_have_a_coresponding_movie()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ public void should_not_delete_extra_files_that_have_a_coresponding_movie()
|
|||||||
public void should_delete_extra_files_that_dont_have_a_coresponding_movie_file()
|
public void should_delete_extra_files_that_dont_have_a_coresponding_movie_file()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ public void should_delete_extra_files_that_dont_have_a_coresponding_movie_file()
|
|||||||
public void should_not_delete_extra_files_that_have_a_coresponding_movie_file()
|
public void should_not_delete_extra_files_that_have_a_coresponding_movie_file()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
var movieFile = Builder<MovieFile>.CreateNew()
|
var movieFile = Builder<MovieFile>.CreateNew()
|
||||||
.With(h => h.Quality = new QualityModel())
|
.With(h => h.Quality = new QualityModel())
|
||||||
|
@ -20,7 +20,7 @@ public class CleanupOrphanedHistoryItemsFixture : DbTest<CleanupOrphanedHistoryI
|
|||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_movie = Builder<Movie>.CreateNew()
|
_movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenSeries()
|
private void GivenSeries()
|
||||||
|
@ -32,7 +32,7 @@ public void should_delete_metadata_files_that_dont_have_a_coresponding_movie()
|
|||||||
public void should_not_delete_metadata_files_that_have_a_coresponding_movie()
|
public void should_not_delete_metadata_files_that_have_a_coresponding_movie()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ public void should_not_delete_metadata_files_that_have_a_coresponding_movie()
|
|||||||
public void should_delete_metadata_files_that_dont_have_a_coresponding_movie_file()
|
public void should_delete_metadata_files_that_dont_have_a_coresponding_movie_file()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ public void should_delete_metadata_files_that_dont_have_a_coresponding_movie_fil
|
|||||||
public void should_not_delete_metadata_files_that_have_a_coresponding_movie_file()
|
public void should_not_delete_metadata_files_that_have_a_coresponding_movie_file()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
var movieFile = Builder<MovieFile>.CreateNew()
|
var movieFile = Builder<MovieFile>.CreateNew()
|
||||||
.With(h => h.Quality = new QualityModel())
|
.With(h => h.Quality = new QualityModel())
|
||||||
@ -92,7 +92,7 @@ public void should_not_delete_metadata_files_that_have_a_coresponding_movie_file
|
|||||||
public void should_delete_movie_metadata_files_that_have_moviefileid_of_zero()
|
public void should_delete_movie_metadata_files_that_have_moviefileid_of_zero()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ public void should_delete_movie_metadata_files_that_have_moviefileid_of_zero()
|
|||||||
public void should_delete_movie_image_files_that_have_moviefileid_of_zero()
|
public void should_delete_movie_image_files_that_have_moviefileid_of_zero()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Housekeeping.Housekeepers;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class CleanupOrphanedMovieTranslationsFixture : DbTest<CleanupOrphanedMovieTranslations, MovieTranslation>
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void should_delete_orphaned_movie_translation_items()
|
||||||
|
{
|
||||||
|
var translation = Builder<MovieTranslation>.CreateNew()
|
||||||
|
.With(h => h.MovieId = default)
|
||||||
|
.With(h => h.Language = Language.English)
|
||||||
|
.BuildNew();
|
||||||
|
|
||||||
|
Db.Insert(translation);
|
||||||
|
Subject.Clean();
|
||||||
|
AllStoredModels.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_delete_unorphaned_movie_translation_items()
|
||||||
|
{
|
||||||
|
var movie = Builder<Movie>.CreateNew().BuildNew();
|
||||||
|
|
||||||
|
Db.Insert(movie);
|
||||||
|
|
||||||
|
var translation = Builder<MovieTranslation>.CreateNew()
|
||||||
|
.With(h => h.MovieId = default)
|
||||||
|
.With(h => h.Language = Language.English)
|
||||||
|
.With(b => b.MovieId = movie.Id)
|
||||||
|
.BuildNew();
|
||||||
|
|
||||||
|
Db.Insert(translation);
|
||||||
|
|
||||||
|
Subject.Clean();
|
||||||
|
AllStoredModels.Should().HaveCount(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
@ -28,12 +28,12 @@ public void should_delete_orphaned_pending_items()
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_not_delete_unorphaned_pending_items()
|
public void should_not_delete_unorphaned_pending_items()
|
||||||
{
|
{
|
||||||
var series = Builder<Movie>.CreateNew().BuildNew();
|
var movie = Builder<Movie>.CreateNew().BuildNew();
|
||||||
|
|
||||||
Db.Insert(series);
|
Db.Insert(movie);
|
||||||
|
|
||||||
var pendingRelease = Builder<PendingRelease>.CreateNew()
|
var pendingRelease = Builder<PendingRelease>.CreateNew()
|
||||||
.With(h => h.MovieId = series.Id)
|
.With(h => h.MovieId = movie.Id)
|
||||||
.With(h => h.ParsedMovieInfo = new ParsedMovieInfo())
|
.With(h => h.ParsedMovieInfo = new ParsedMovieInfo())
|
||||||
.With(h => h.Release = new ReleaseInfo())
|
.With(h => h.Release = new ReleaseInfo())
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
@ -32,7 +32,7 @@ public void should_delete_subtitle_files_that_dont_have_a_coresponding_movie()
|
|||||||
public void should_not_delete_subtitle_files_that_have_a_coresponding_movie()
|
public void should_not_delete_subtitle_files_that_have_a_coresponding_movie()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ public void should_not_delete_subtitle_files_that_have_a_coresponding_movie()
|
|||||||
public void should_delete_subtitle_files_that_dont_have_a_coresponding_movie_file()
|
public void should_delete_subtitle_files_that_dont_have_a_coresponding_movie_file()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(movie);
|
Db.Insert(movie);
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ public void should_delete_subtitle_files_that_dont_have_a_coresponding_movie_fil
|
|||||||
public void should_not_delete_subtitle_files_that_have_a_coresponding_movie_file()
|
public void should_not_delete_subtitle_files_that_have_a_coresponding_movie_file()
|
||||||
{
|
{
|
||||||
var movie = Builder<Movie>.CreateNew()
|
var movie = Builder<Movie>.CreateNew()
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
var movieFile = Builder<MovieFile>.CreateNew()
|
var movieFile = Builder<MovieFile>.CreateNew()
|
||||||
.With(h => h.Quality = new QualityModel())
|
.With(h => h.Quality = new QualityModel())
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -24,7 +25,8 @@ public void Setup()
|
|||||||
|
|
||||||
_movieSearchCriteria = new MovieSearchCriteria
|
_movieSearchCriteria = new MovieSearchCriteria
|
||||||
{
|
{
|
||||||
Movie = new Movies.Movie { ImdbId = "tt0076759", Title = "Star Wars", Year = 1977 }
|
Movie = new Movies.Movie { ImdbId = "tt0076759", Title = "Star Wars", Year = 1977 },
|
||||||
|
SceneTitles = new List<string> { "Star Wars" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ public void should_search_by_name_and_year_if_missing_imdbid()
|
|||||||
var page = results.GetAllTiers().First().First();
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
page.Url.Query.Should().Contain("type=name");
|
page.Url.Query.Should().Contain("type=name");
|
||||||
page.Url.Query.Should().Contain("query=Star Wars 1977");
|
page.Url.Query.Should().Contain("query=Star+Wars+1977");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
@ -25,7 +26,8 @@ public void SetUp()
|
|||||||
|
|
||||||
_movieSearchCriteria = new MovieSearchCriteria
|
_movieSearchCriteria = new MovieSearchCriteria
|
||||||
{
|
{
|
||||||
Movie = new Movies.Movie { ImdbId = "tt0076759", Title = "Star Wars", Year = 1977 }
|
Movie = new Movies.Movie { ImdbId = "tt0076759", Title = "Star Wars", Year = 1977, TmdbId = 11 },
|
||||||
|
SceneTitles = new List<string> { "Star Wars" }
|
||||||
};
|
};
|
||||||
|
|
||||||
_capabilities = new NewznabCapabilities();
|
_capabilities = new NewznabCapabilities();
|
||||||
@ -66,7 +68,7 @@ public void should_return_subsequent_pages()
|
|||||||
{
|
{
|
||||||
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
|
||||||
results.GetAllTiers().Should().HaveCount(1);
|
results.GetAllTiers().Should().HaveCount(2);
|
||||||
|
|
||||||
var pages = results.GetAllTiers().First().Take(3).ToList();
|
var pages = results.GetAllTiers().First().Take(3).ToList();
|
||||||
|
|
||||||
@ -80,7 +82,7 @@ public void should_not_get_unlimited_pages()
|
|||||||
{
|
{
|
||||||
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
|
||||||
results.GetAllTiers().Should().HaveCount(1);
|
results.GetAllTiers().Should().HaveCount(2);
|
||||||
|
|
||||||
var pages = results.GetAllTiers().First().Take(500).ToList();
|
var pages = results.GetAllTiers().First().Take(500).ToList();
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ public void should_not_search_by_imdbid_if_not_supported()
|
|||||||
var page = results.GetAllTiers().First().First();
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
page.Url.Query.Should().NotContain("imdbid=0076759");
|
page.Url.Query.Should().NotContain("imdbid=0076759");
|
||||||
page.Url.Query.Should().Contain("q=star");
|
page.Url.Query.Should().Contain("q=Star");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -114,5 +116,93 @@ public void should_search_by_imdbid_if_supported()
|
|||||||
|
|
||||||
page.Url.Query.Should().Contain("imdbid=0076759");
|
page.Url.Query.Should().Contain("imdbid=0076759");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_search_by_tmdbid_if_supported()
|
||||||
|
{
|
||||||
|
_capabilities.SupportedMovieSearchParameters = new[] { "q", "tmdbid" };
|
||||||
|
|
||||||
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
results.GetTier(0).Should().HaveCount(1);
|
||||||
|
|
||||||
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
|
page.Url.Query.Should().Contain("tmdbid=11");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_prefer_search_by_tmdbid_if_rid_supported()
|
||||||
|
{
|
||||||
|
_capabilities.SupportedMovieSearchParameters = new[] { "q", "tmdbid", "imdbid" };
|
||||||
|
|
||||||
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
results.GetTier(0).Should().HaveCount(1);
|
||||||
|
|
||||||
|
var page = results.GetAllTiers().First().First();
|
||||||
|
|
||||||
|
page.Url.Query.Should().Contain("tmdbid=11");
|
||||||
|
page.Url.Query.Should().NotContain("imdbid=0076759");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_use_aggregrated_id_search_if_supported()
|
||||||
|
{
|
||||||
|
_capabilities.SupportedMovieSearchParameters = new[] { "q", "tmdbid", "imdbid" };
|
||||||
|
_capabilities.SupportsAggregateIdSearch = true;
|
||||||
|
|
||||||
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
results.GetTier(0).Should().HaveCount(1);
|
||||||
|
|
||||||
|
var page = results.GetTier(0).First().First();
|
||||||
|
|
||||||
|
page.Url.Query.Should().Contain("tmdbid=11");
|
||||||
|
page.Url.Query.Should().Contain("imdbid=0076759");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_use_aggregrated_id_search_if_no_ids_supported()
|
||||||
|
{
|
||||||
|
_capabilities.SupportedMovieSearchParameters = new[] { "q" };
|
||||||
|
_capabilities.SupportsAggregateIdSearch = true; // Turns true if indexer supplies supportedParams.
|
||||||
|
|
||||||
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
results.Tiers.Should().Be(1);
|
||||||
|
results.GetTier(0).Should().HaveCount(1);
|
||||||
|
|
||||||
|
var page = results.GetTier(0).First().First();
|
||||||
|
|
||||||
|
page.Url.Query.Should().Contain("q=");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_use_aggregrated_id_search_if_no_ids_are_known()
|
||||||
|
{
|
||||||
|
_capabilities.SupportedMovieSearchParameters = new[] { "q", "imdbid" };
|
||||||
|
_capabilities.SupportsAggregateIdSearch = true; // Turns true if indexer supplies supportedParams.
|
||||||
|
|
||||||
|
_movieSearchCriteria.Movie.ImdbId = null;
|
||||||
|
|
||||||
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
|
||||||
|
var page = results.GetTier(0).First().First();
|
||||||
|
|
||||||
|
page.Url.Query.Should().Contain("q=");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_fallback_to_q()
|
||||||
|
{
|
||||||
|
_capabilities.SupportedMovieSearchParameters = new[] { "q", "tmdbid", "imdbid" };
|
||||||
|
_capabilities.SupportsAggregateIdSearch = true;
|
||||||
|
|
||||||
|
var results = Subject.GetSearchRequests(_movieSearchCriteria);
|
||||||
|
results.Tiers.Should().Be(2);
|
||||||
|
|
||||||
|
var pageTier2 = results.GetTier(1).First().First();
|
||||||
|
|
||||||
|
pageTier2.Url.Query.Should().NotContain("tmdbid=11");
|
||||||
|
pageTier2.Url.Query.Should().NotContain("imdbid=0076759");
|
||||||
|
pageTier2.Url.Query.Should().Contain("q=");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ private ParsedMovieInfo GetParsedMovieInfo(List<Language> languages)
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_return_default_if_no_info_is_known()
|
public void should_return_default_if_no_info_is_known()
|
||||||
{
|
{
|
||||||
Subject.Aggregate(_localMovie, false).Languages.Should().Contain(Language.English);
|
Subject.Aggregate(_localMovie, false).Languages.Should().Contain(Language.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -70,8 +70,8 @@ public void should_return_download_client_item_language_when_download_client_ite
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_return_file_language_when_file_language_is_higher_than_others()
|
public void should_return_file_language_when_file_language_is_higher_than_others()
|
||||||
{
|
{
|
||||||
_localMovie.DownloadClientMovieInfo = GetParsedMovieInfo(new List<Language> { Language.English });
|
_localMovie.DownloadClientMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Unknown });
|
||||||
_localMovie.FolderMovieInfo = GetParsedMovieInfo(new List<Language> { Language.English });
|
_localMovie.FolderMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Unknown });
|
||||||
_localMovie.FileMovieInfo = GetParsedMovieInfo(new List<Language> { Language.French });
|
_localMovie.FileMovieInfo = GetParsedMovieInfo(new List<Language> { Language.French });
|
||||||
|
|
||||||
Subject.Aggregate(_localMovie, false).Languages.Should().Equal(_localMovie.FileMovieInfo.Languages);
|
Subject.Aggregate(_localMovie, false).Languages.Should().Equal(_localMovie.FileMovieInfo.Languages);
|
||||||
@ -80,9 +80,9 @@ public void should_return_file_language_when_file_language_is_higher_than_others
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_return_multi_language()
|
public void should_return_multi_language()
|
||||||
{
|
{
|
||||||
_localMovie.DownloadClientMovieInfo = GetParsedMovieInfo(new List<Language> { Language.English });
|
_localMovie.DownloadClientMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Unknown });
|
||||||
_localMovie.FolderMovieInfo = GetParsedMovieInfo(new List<Language> { Language.English, Language.German });
|
_localMovie.FolderMovieInfo = GetParsedMovieInfo(new List<Language> { Language.English, Language.German });
|
||||||
_localMovie.FileMovieInfo = GetParsedMovieInfo(new List<Language> { Language.English });
|
_localMovie.FileMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Unknown });
|
||||||
|
|
||||||
Subject.Aggregate(_localMovie, false).Languages.Should().Equal(_localMovie.FolderMovieInfo.Languages);
|
Subject.Aggregate(_localMovie, false).Languages.Should().Equal(_localMovie.FolderMovieInfo.Languages);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
using NzbDrone.Core.MetadataSource;
|
using NzbDrone.Core.MetadataSource;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.Credits;
|
using NzbDrone.Core.Movies.Credits;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
@ -27,7 +27,10 @@ public void Setup()
|
|||||||
_title1 = titles[0];
|
_title1 = titles[0];
|
||||||
_title2 = titles[1];
|
_title2 = titles[1];
|
||||||
_title3 = titles[2];
|
_title3 = titles[2];
|
||||||
_movie = Builder<Movie>.CreateNew().With(m => m.CleanTitle = "myothertitle").With(m => m.Id = 1).Build();
|
_movie = Builder<Movie>.CreateNew()
|
||||||
|
.With(m => m.CleanTitle = "myothertitle")
|
||||||
|
.With(m => m.Id = 1)
|
||||||
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenExistingTitles(params AlternativeTitle[] titles)
|
private void GivenExistingTitles(params AlternativeTitle[] titles)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.CustomFormats;
|
using NzbDrone.Core.CustomFormats;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
@ -30,7 +30,7 @@ public void Setup()
|
|||||||
_episodeFile = new MovieFile { Quality = new QualityModel(), ReleaseGroup = "SonarrTest" };
|
_episodeFile = new MovieFile { Quality = new QualityModel(), ReleaseGroup = "SonarrTest" };
|
||||||
|
|
||||||
_namingConfig = NamingConfig.Default;
|
_namingConfig = NamingConfig.Default;
|
||||||
_namingConfig.RenameEpisodes = true;
|
_namingConfig.RenameMovies = true;
|
||||||
|
|
||||||
Mocker.GetMock<INamingConfigService>()
|
Mocker.GetMock<INamingConfigService>()
|
||||||
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
||||||
|
@ -6,9 +6,11 @@
|
|||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.CustomFormats;
|
using NzbDrone.Core.CustomFormats;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
@ -21,18 +23,34 @@ public class FileNameBuilderFixture : CoreTest<FileNameBuilder>
|
|||||||
{
|
{
|
||||||
private Movie _movie;
|
private Movie _movie;
|
||||||
private MovieFile _movieFile;
|
private MovieFile _movieFile;
|
||||||
|
private List<MovieTranslation> _movieTranslations;
|
||||||
private NamingConfig _namingConfig;
|
private NamingConfig _namingConfig;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
|
_movieTranslations = new List<MovieTranslation>
|
||||||
|
{
|
||||||
|
new MovieTranslation
|
||||||
|
{
|
||||||
|
Language = Language.German,
|
||||||
|
Title = "German South Park"
|
||||||
|
},
|
||||||
|
|
||||||
|
new MovieTranslation
|
||||||
|
{
|
||||||
|
Language = Language.French,
|
||||||
|
Title = "French South Park"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
_movie = Builder<Movie>
|
_movie = Builder<Movie>
|
||||||
.CreateNew()
|
.CreateNew()
|
||||||
.With(s => s.Title = "South Park")
|
.With(s => s.Title = "South Park")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_namingConfig = NamingConfig.Default;
|
_namingConfig = NamingConfig.Default;
|
||||||
_namingConfig.RenameEpisodes = true;
|
_namingConfig.RenameMovies = true;
|
||||||
|
|
||||||
Mocker.GetMock<INamingConfigService>()
|
Mocker.GetMock<INamingConfigService>()
|
||||||
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
||||||
@ -46,6 +64,10 @@ public void Setup()
|
|||||||
Mocker.GetMock<ICustomFormatService>()
|
Mocker.GetMock<ICustomFormatService>()
|
||||||
.Setup(v => v.All())
|
.Setup(v => v.All())
|
||||||
.Returns(new List<CustomFormat>());
|
.Returns(new List<CustomFormat>());
|
||||||
|
|
||||||
|
Mocker.GetMock<IMovieTranslationService>()
|
||||||
|
.Setup(v => v.GetAllTranslationsForMovie(It.IsAny<int>()))
|
||||||
|
.Returns(_movieTranslations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenProper()
|
private void GivenProper()
|
||||||
@ -121,6 +143,51 @@ public void should_replace_movie_title_with_all_lower_case()
|
|||||||
.Should().Be("south park");
|
.Should().Be("south park");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_translated_movie_title()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardMovieFormat = "{Movie Title:FR}";
|
||||||
|
|
||||||
|
Subject.BuildFileName(_movie, _movieFile)
|
||||||
|
.Should().Be("French South Park");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_translated_movie_title_with_base_title_if_invalid_code()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardMovieFormat = "{Movie Title:JP}";
|
||||||
|
|
||||||
|
Subject.BuildFileName(_movie, _movieFile)
|
||||||
|
.Should().Be("South Park");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_translated_movie_title_with_base_title_if_no_translation_exists()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardMovieFormat = "{Movie Title:JA}";
|
||||||
|
|
||||||
|
Subject.BuildFileName(_movie, _movieFile)
|
||||||
|
.Should().Be("South Park");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_translated_movie_title_with_fallback_if_no_translation_exists()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardMovieFormat = "{Movie Title:JP|FR}";
|
||||||
|
|
||||||
|
Subject.BuildFileName(_movie, _movieFile)
|
||||||
|
.Should().Be("French South Park");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_replace_translated_movie_title_with_original_if_no_translation_or_fallback_exists()
|
||||||
|
{
|
||||||
|
_namingConfig.StandardMovieFormat = "{Movie Title:JP|CN}";
|
||||||
|
|
||||||
|
Subject.BuildFileName(_movie, _movieFile)
|
||||||
|
.Should().Be("South Park");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_cleanup_Movie_Title()
|
public void should_cleanup_Movie_Title()
|
||||||
{
|
{
|
||||||
@ -172,7 +239,7 @@ public void should_replace_all_contents_in_pattern()
|
|||||||
[Test]
|
[Test]
|
||||||
public void use_file_name_when_sceneName_is_null()
|
public void use_file_name_when_sceneName_is_null()
|
||||||
{
|
{
|
||||||
_namingConfig.RenameEpisodes = false;
|
_namingConfig.RenameMovies = false;
|
||||||
_movieFile.RelativePath = "30 Rock - S01E01 - Test";
|
_movieFile.RelativePath = "30 Rock - S01E01 - Test";
|
||||||
|
|
||||||
Subject.BuildFileName(_movie, _movieFile)
|
Subject.BuildFileName(_movie, _movieFile)
|
||||||
@ -182,7 +249,7 @@ public void use_file_name_when_sceneName_is_null()
|
|||||||
[Test]
|
[Test]
|
||||||
public void use_path_when_sceneName_and_relative_path_are_null()
|
public void use_path_when_sceneName_and_relative_path_are_null()
|
||||||
{
|
{
|
||||||
_namingConfig.RenameEpisodes = false;
|
_namingConfig.RenameMovies = false;
|
||||||
_movieFile.RelativePath = null;
|
_movieFile.RelativePath = null;
|
||||||
_movieFile.Path = @"C:\Test\Unsorted\Movie - S01E01 - Test";
|
_movieFile.Path = @"C:\Test\Unsorted\Movie - S01E01 - Test";
|
||||||
|
|
||||||
@ -193,7 +260,7 @@ public void use_path_when_sceneName_and_relative_path_are_null()
|
|||||||
[Test]
|
[Test]
|
||||||
public void use_file_name_when_sceneName_is_not_null()
|
public void use_file_name_when_sceneName_is_not_null()
|
||||||
{
|
{
|
||||||
_namingConfig.RenameEpisodes = false;
|
_namingConfig.RenameMovies = false;
|
||||||
_movieFile.SceneName = "30.Rock.S01E01.xvid-LOL";
|
_movieFile.SceneName = "30.Rock.S01E01.xvid-LOL";
|
||||||
_movieFile.RelativePath = "30 Rock - S01E01 - Test";
|
_movieFile.RelativePath = "30 Rock - S01E01 - Test";
|
||||||
|
|
||||||
@ -317,7 +384,7 @@ public void should_remove_duplicate_non_word_characters()
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_use_existing_filename_when_scene_name_is_not_available()
|
public void should_use_existing_filename_when_scene_name_is_not_available()
|
||||||
{
|
{
|
||||||
_namingConfig.RenameEpisodes = true;
|
_namingConfig.RenameMovies = true;
|
||||||
_namingConfig.StandardMovieFormat = "{Original Title}";
|
_namingConfig.StandardMovieFormat = "{Original Title}";
|
||||||
|
|
||||||
_movieFile.SceneName = null;
|
_movieFile.SceneName = null;
|
||||||
|
@ -24,7 +24,7 @@ public void Setup()
|
|||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_namingConfig = NamingConfig.Default;
|
_namingConfig = NamingConfig.Default;
|
||||||
_namingConfig.RenameEpisodes = true;
|
_namingConfig.RenameMovies = true;
|
||||||
|
|
||||||
Mocker.GetMock<INamingConfigService>()
|
Mocker.GetMock<INamingConfigService>()
|
||||||
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
||||||
|
@ -30,7 +30,7 @@ public void Setup()
|
|||||||
_movieFile = new MovieFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "RadarrTest" };
|
_movieFile = new MovieFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "RadarrTest" };
|
||||||
|
|
||||||
_namingConfig = NamingConfig.Default;
|
_namingConfig = NamingConfig.Default;
|
||||||
_namingConfig.RenameEpisodes = true;
|
_namingConfig.RenameMovies = true;
|
||||||
|
|
||||||
Mocker.GetMock<INamingConfigService>()
|
Mocker.GetMock<INamingConfigService>()
|
||||||
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
.Setup(c => c.GetConfig()).Returns(_namingConfig);
|
||||||
|
@ -11,8 +11,6 @@ namespace NzbDrone.Core.Test.ParserTests
|
|||||||
public class LanguageParserFixture : CoreTest
|
public class LanguageParserFixture : CoreTest
|
||||||
{
|
{
|
||||||
[TestCase("Pulp.Fiction.1994.English.1080p.XviD-LOL")]
|
[TestCase("Pulp.Fiction.1994.English.1080p.XviD-LOL")]
|
||||||
[TestCase("The Danish Girl 2015")]
|
|
||||||
[TestCase("Fantastic.Beasts.The.Crimes.Of.Grindelwald.2018.2160p.WEBRip.x265.10bit.HDR.DD5.1-GASMASK")]
|
|
||||||
public void should_parse_language_english(string postTitle)
|
public void should_parse_language_english(string postTitle)
|
||||||
{
|
{
|
||||||
var result = Parser.Parser.ParseMovieTitle(postTitle, true);
|
var result = Parser.Parser.ParseMovieTitle(postTitle, true);
|
||||||
@ -20,6 +18,15 @@ public void should_parse_language_english(string postTitle)
|
|||||||
result.Languages.Should().BeEquivalentTo(Language.English);
|
result.Languages.Should().BeEquivalentTo(Language.English);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("The Danish Girl 2015")]
|
||||||
|
[TestCase("Fantastic.Beasts.The.Crimes.Of.Grindelwald.2018.2160p.WEBRip.x265.10bit.HDR.DD5.1-GASMASK")]
|
||||||
|
public void should_parse_language_unknown(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseMovieTitle(postTitle, true);
|
||||||
|
|
||||||
|
result.Languages.Should().BeEquivalentTo(Language.Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase("Pulp.Fiction.1994.French.1080p.XviD-LOL")]
|
[TestCase("Pulp.Fiction.1994.French.1080p.XviD-LOL")]
|
||||||
public void should_parse_language_french(string postTitle)
|
public void should_parse_language_french(string postTitle)
|
||||||
{
|
{
|
||||||
@ -28,6 +35,15 @@ public void should_parse_language_french(string postTitle)
|
|||||||
result.Languages.Should().BeEquivalentTo(Language.French);
|
result.Languages.Should().BeEquivalentTo(Language.French);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("E.T. the Extra-Terrestrial.1982.Ger.Eng.AC3.DL.BDRip.x264-iNCEPTiON")]
|
||||||
|
public void should_parse_language_english_german(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseMovieTitle(postTitle, true);
|
||||||
|
|
||||||
|
result.Languages.Should().Contain(Language.German);
|
||||||
|
result.Languages.Should().Contain(Language.English);
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase("Pulp.Fiction.1994.Spanish.1080p.XviD-LOL")]
|
[TestCase("Pulp.Fiction.1994.Spanish.1080p.XviD-LOL")]
|
||||||
public void should_parse_language_spanish(string postTitle)
|
public void should_parse_language_spanish(string postTitle)
|
||||||
{
|
{
|
||||||
|
@ -171,7 +171,7 @@ public void should_not_parse_wrong_language_in_title(string postTitle)
|
|||||||
{
|
{
|
||||||
var parsed = Parser.Parser.ParseMovieTitle(postTitle, true);
|
var parsed = Parser.Parser.ParseMovieTitle(postTitle, true);
|
||||||
parsed.Languages.Count().Should().Be(1);
|
parsed.Languages.Count().Should().Be(1);
|
||||||
parsed.Languages.First().Should().Be(Language.English);
|
parsed.Languages.First().Should().Be(Language.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("The.Purge.3.Election.Year.2016.German.DTS.DL.720p.BluRay.x264-MULTiPLEX")]
|
[TestCase("The.Purge.3.Election.Year.2016.German.DTS.DL.720p.BluRay.x264-MULTiPLEX")]
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
@ -34,47 +35,55 @@ public void Setup()
|
|||||||
.With(m => m.CleanTitle = "fackjugoethe2")
|
.With(m => m.CleanTitle = "fackjugoethe2")
|
||||||
.With(m => m.Year = 2015)
|
.With(m => m.Year = 2015)
|
||||||
.With(m => m.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
|
.With(m => m.AlternativeTitles = new List<AlternativeTitle> { new AlternativeTitle("Fack Ju Göthe 2: Same same") })
|
||||||
|
.With(m => m.OriginalLanguage = Language.English)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_parsedMovieInfo = new ParsedMovieInfo
|
_parsedMovieInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = _movie.Title,
|
MovieTitle = _movie.Title,
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = _movie.Year,
|
Year = _movie.Year,
|
||||||
};
|
};
|
||||||
|
|
||||||
_wrongYearInfo = new ParsedMovieInfo
|
_wrongYearInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = _movie.Title,
|
MovieTitle = _movie.Title,
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = 1900,
|
Year = 1900,
|
||||||
};
|
};
|
||||||
|
|
||||||
_wrongTitleInfo = new ParsedMovieInfo
|
_wrongTitleInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = "Other Title",
|
MovieTitle = "Other Title",
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = 2015
|
Year = 2015
|
||||||
};
|
};
|
||||||
|
|
||||||
_alternativeTitleInfo = new ParsedMovieInfo
|
_alternativeTitleInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = _movie.AlternativeTitles.First().Title,
|
MovieTitle = _movie.AlternativeTitles.First().Title,
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = _movie.Year,
|
Year = _movie.Year,
|
||||||
};
|
};
|
||||||
|
|
||||||
_romanTitleInfo = new ParsedMovieInfo
|
_romanTitleInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = "Fack Ju Göthe II",
|
MovieTitle = "Fack Ju Göthe II",
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = _movie.Year,
|
Year = _movie.Year,
|
||||||
};
|
};
|
||||||
|
|
||||||
_umlautInfo = new ParsedMovieInfo
|
_umlautInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = "Fack Ju Goethe 2",
|
MovieTitle = "Fack Ju Goethe 2",
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = _movie.Year
|
Year = _movie.Year
|
||||||
};
|
};
|
||||||
|
|
||||||
_umlautAltInfo = new ParsedMovieInfo
|
_umlautAltInfo = new ParsedMovieInfo
|
||||||
{
|
{
|
||||||
MovieTitle = "Fack Ju Goethe 2: Same same",
|
MovieTitle = "Fack Ju Goethe 2: Same same",
|
||||||
|
Languages = new List<Language> { Language.English },
|
||||||
Year = _movie.Year
|
Year = _movie.Year
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.CustomFormats;
|
using NzbDrone.Core.CustomFormats;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.NetImport;
|
using NzbDrone.Core.NetImport;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles;
|
||||||
|
using NzbDrone.Core.Test.CustomFormats;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Profiles
|
namespace NzbDrone.Core.Test.Profiles
|
||||||
@ -107,5 +110,45 @@ public void should_delete_profile_if_not_assigned_to_movie_or_list()
|
|||||||
|
|
||||||
Mocker.GetMock<IProfileRepository>().Verify(c => c.Delete(1), Times.Once());
|
Mocker.GetMock<IProfileRepository>().Verify(c => c.Delete(1), Times.Once());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void get_acceptable_languages_should_return_profile_language()
|
||||||
|
{
|
||||||
|
var profile = Builder<Profile>.CreateNew().With(c => c.Language = Language.German).Build();
|
||||||
|
|
||||||
|
Mocker.GetMock<IProfileRepository>()
|
||||||
|
.Setup(s => s.Get(It.IsAny<int>()))
|
||||||
|
.Returns(profile);
|
||||||
|
|
||||||
|
var languages = Subject.GetAcceptableLanguages(profile.Id);
|
||||||
|
|
||||||
|
languages.Count.Should().Be(1);
|
||||||
|
languages.Should().Contain(Language.German);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void get_acceptable_languages_should_return_custom_format_positive_languages()
|
||||||
|
{
|
||||||
|
var profile = Builder<Profile>.CreateNew()
|
||||||
|
.With(c => c.Language = Language.German)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var customFormat1 = new CustomFormat("My Format 1", new LanguageSpecification { Value = (int)Language.English }) { Id = 1 };
|
||||||
|
var customFormat2 = new CustomFormat("My Format 2", new LanguageSpecification { Value = (int)Language.French }) { Id = 2 };
|
||||||
|
|
||||||
|
CustomFormatsFixture.GivenCustomFormats(customFormat1, customFormat2);
|
||||||
|
|
||||||
|
profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(customFormat2.Name);
|
||||||
|
|
||||||
|
Mocker.GetMock<IProfileRepository>()
|
||||||
|
.Setup(s => s.Get(It.IsAny<int>()))
|
||||||
|
.Returns(profile);
|
||||||
|
|
||||||
|
var languages = Subject.GetAcceptableLanguages(profile.Id);
|
||||||
|
|
||||||
|
languages.Count.Should().Be(2);
|
||||||
|
languages.Should().Contain(Language.German);
|
||||||
|
languages.Should().Contain(Language.French);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
using NzbDrone.Common.Http.Proxy;
|
using NzbDrone.Common.Http.Proxy;
|
||||||
using NzbDrone.Core.Configuration.Events;
|
using NzbDrone.Core.Configuration.Events;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||||
@ -371,6 +372,13 @@ public bool EnableColorImpairedMode
|
|||||||
set { SetValue("EnableColorImpairedMode", value); }
|
set { SetValue("EnableColorImpairedMode", value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int MovieInfoLanguage
|
||||||
|
{
|
||||||
|
get { return GetValueInt("MovieInfoLanguage", (int)Language.English); }
|
||||||
|
|
||||||
|
set { SetValue("MovieInfoLanguage", value); }
|
||||||
|
}
|
||||||
|
|
||||||
public bool CleanupMetadataImages
|
public bool CleanupMetadataImages
|
||||||
{
|
{
|
||||||
get { return GetValueBoolean("CleanupMetadataImages", true); }
|
get { return GetValueBoolean("CleanupMetadataImages", true); }
|
||||||
|
@ -75,6 +75,7 @@ public interface IConfigService
|
|||||||
string TimeFormat { get; set; }
|
string TimeFormat { get; set; }
|
||||||
bool ShowRelativeDates { get; set; }
|
bool ShowRelativeDates { get; set; }
|
||||||
bool EnableColorImpairedMode { get; set; }
|
bool EnableColorImpairedMode { get; set; }
|
||||||
|
int MovieInfoLanguage { get; set; }
|
||||||
|
|
||||||
//Internal
|
//Internal
|
||||||
bool CleanupMetadataImages { get; set; }
|
bool CleanupMetadataImages { get; set; }
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Dapper;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(177)]
|
||||||
|
public class language_improvements : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
private readonly JsonSerializerOptions _serializerSettings;
|
||||||
|
|
||||||
|
public language_improvements()
|
||||||
|
{
|
||||||
|
_serializerSettings = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
AllowTrailingCommas = true,
|
||||||
|
IgnoreNullValues = false,
|
||||||
|
PropertyNameCaseInsensitive = true,
|
||||||
|
DictionaryKeyPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
// Use original language to set default language fallback for releases
|
||||||
|
// Set all to English (1) on migration to ensure default behavior persists until refresh
|
||||||
|
Alter.Table("Movies").AddColumn("OriginalLanguage").AsInt32().WithDefaultValue((int)Language.English);
|
||||||
|
Alter.Table("Movies").AddColumn("OriginalTitle").AsString().Nullable();
|
||||||
|
|
||||||
|
Alter.Table("Movies").AddColumn("DigitalRelease").AsDateTime().Nullable();
|
||||||
|
|
||||||
|
// Column not used
|
||||||
|
Delete.Column("PhysicalReleaseNote").FromTable("Movies");
|
||||||
|
Delete.Column("SecondaryYearSourceId").FromTable("Movies");
|
||||||
|
|
||||||
|
Alter.Table("NamingConfig").AddColumn("RenameMovies").AsBoolean().WithDefaultValue(0);
|
||||||
|
Execute.Sql("UPDATE NamingConfig SET RenameMovies=RenameEpisodes");
|
||||||
|
Delete.Column("RenameEpisodes").FromTable("NamingConfig");
|
||||||
|
|
||||||
|
//Manual SQL, Fluent Migrator doesn't support multi-column unique contraint on table creation, SQLite doesn't support adding it after creation
|
||||||
|
Execute.Sql("CREATE TABLE MovieTranslations(" +
|
||||||
|
"Id INTEGER PRIMARY KEY, " +
|
||||||
|
"MovieId INTEGER NOT NULL, " +
|
||||||
|
"Title TEXT, " +
|
||||||
|
"CleanTitle TEXT, " +
|
||||||
|
"Overview TEXT, " +
|
||||||
|
"Language INTEGER NOT NULL, " +
|
||||||
|
"Unique(\"MovieId\", \"Language\"));");
|
||||||
|
|
||||||
|
// Prevent failure if two movies have same alt titles
|
||||||
|
Execute.Sql("DROP INDEX IF EXISTS \"IX_AlternativeTitles_CleanTitle\"");
|
||||||
|
|
||||||
|
Execute.WithConnection(FixLanguagesMoveFile);
|
||||||
|
Execute.WithConnection(FixLanguagesHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixLanguagesMoveFile(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var rows = conn.Query<LanguageEntity177>($"SELECT Id, Languages FROM MovieFiles");
|
||||||
|
|
||||||
|
var corrected = new List<LanguageEntity177>();
|
||||||
|
|
||||||
|
foreach (var row in rows)
|
||||||
|
{
|
||||||
|
var languages = JsonSerializer.Deserialize<List<int>>(row.Languages, _serializerSettings);
|
||||||
|
|
||||||
|
var newLanguages = languages.Distinct().ToList();
|
||||||
|
|
||||||
|
corrected.Add(new LanguageEntity177
|
||||||
|
{
|
||||||
|
Id = row.Id,
|
||||||
|
Languages = JsonSerializer.Serialize(newLanguages, _serializerSettings)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateSql = "UPDATE MovieFiles SET Languages = @Languages WHERE Id = @Id";
|
||||||
|
conn.Execute(updateSql, corrected, transaction: tran);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FixLanguagesHistory(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var rows = conn.Query<LanguageEntity177>($"SELECT Id, Languages FROM History");
|
||||||
|
|
||||||
|
var corrected = new List<LanguageEntity177>();
|
||||||
|
|
||||||
|
foreach (var row in rows)
|
||||||
|
{
|
||||||
|
var languages = JsonSerializer.Deserialize<List<int>>(row.Languages, _serializerSettings);
|
||||||
|
|
||||||
|
var newLanguages = languages.Distinct().ToList();
|
||||||
|
|
||||||
|
corrected.Add(new LanguageEntity177
|
||||||
|
{
|
||||||
|
Id = row.Id,
|
||||||
|
Languages = JsonSerializer.Serialize(newLanguages, _serializerSettings)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateSql = "UPDATE History SET Languages = @Languages WHERE Id = @Id";
|
||||||
|
conn.Execute(updateSql, corrected, transaction: tran);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LanguageEntity177 : ModelBase
|
||||||
|
{
|
||||||
|
public string Languages { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@
|
|||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||||
using NzbDrone.Core.Movies.Credits;
|
using NzbDrone.Core.Movies.Credits;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.NetImport;
|
using NzbDrone.Core.NetImport;
|
||||||
using NzbDrone.Core.NetImport.ImportExclusions;
|
using NzbDrone.Core.NetImport.ImportExclusions;
|
||||||
using NzbDrone.Core.Notifications;
|
using NzbDrone.Core.Notifications;
|
||||||
@ -105,6 +106,8 @@ public static void Map()
|
|||||||
|
|
||||||
Mapper.Entity<AlternativeTitle>("AlternativeTitles").RegisterModel();
|
Mapper.Entity<AlternativeTitle>("AlternativeTitles").RegisterModel();
|
||||||
|
|
||||||
|
Mapper.Entity<MovieTranslation>("MovieTranslations").RegisterModel();
|
||||||
|
|
||||||
Mapper.Entity<Credit>("Credits").RegisterModel();
|
Mapper.Entity<Credit>("Credits").RegisterModel();
|
||||||
|
|
||||||
Mapper.Entity<ImportExclusion>("ImportExclusions").RegisterModel();
|
Mapper.Entity<ImportExclusion>("ImportExclusions").RegisterModel();
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
using Dapper;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||||
|
{
|
||||||
|
public class CleanupOrphanedMovieTranslations : IHousekeepingTask
|
||||||
|
{
|
||||||
|
private readonly IMainDatabase _database;
|
||||||
|
|
||||||
|
public CleanupOrphanedMovieTranslations(IMainDatabase database)
|
||||||
|
{
|
||||||
|
_database = database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clean()
|
||||||
|
{
|
||||||
|
using (var mapper = _database.OpenConnection())
|
||||||
|
{
|
||||||
|
mapper.Execute(@"DELETE FROM MovieTranslations
|
||||||
|
WHERE Id IN (
|
||||||
|
SELECT MovieTranslations.Id FROM MovieTranslations
|
||||||
|
LEFT OUTER JOIN Movies
|
||||||
|
ON MovieTranslations.MovieId = Movies.Id
|
||||||
|
WHERE Movies.Id IS NULL)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,9 @@
|
|||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Profiles;
|
||||||
|
|
||||||
namespace NzbDrone.Core.IndexerSearch
|
namespace NzbDrone.Core.IndexerSearch
|
||||||
{
|
{
|
||||||
@ -24,16 +26,22 @@ public class NzbSearchService : ISearchForNzb
|
|||||||
private readonly IIndexerFactory _indexerFactory;
|
private readonly IIndexerFactory _indexerFactory;
|
||||||
private readonly IMakeDownloadDecision _makeDownloadDecision;
|
private readonly IMakeDownloadDecision _makeDownloadDecision;
|
||||||
private readonly IMovieService _movieService;
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly IMovieTranslationService _movieTranslationService;
|
||||||
|
private readonly IProfileService _profileService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public NzbSearchService(IIndexerFactory indexerFactory,
|
public NzbSearchService(IIndexerFactory indexerFactory,
|
||||||
IMakeDownloadDecision makeDownloadDecision,
|
IMakeDownloadDecision makeDownloadDecision,
|
||||||
IMovieService movieService,
|
IMovieService movieService,
|
||||||
|
IMovieTranslationService movieTranslationService,
|
||||||
|
IProfileService profileService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_indexerFactory = indexerFactory;
|
_indexerFactory = indexerFactory;
|
||||||
_makeDownloadDecision = makeDownloadDecision;
|
_makeDownloadDecision = makeDownloadDecision;
|
||||||
_movieService = movieService;
|
_movieService = movieService;
|
||||||
|
_movieTranslationService = movieTranslationService;
|
||||||
|
_profileService = profileService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +68,24 @@ private TSpec Get<TSpec>(Movie movie, bool userInvokedSearch, bool interactiveSe
|
|||||||
UserInvokedSearch = userInvokedSearch,
|
UserInvokedSearch = userInvokedSearch,
|
||||||
InteractiveSearch = interactiveSearch
|
InteractiveSearch = interactiveSearch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var wantedLanguages = _profileService.GetAcceptableLanguages(movie.ProfileId);
|
||||||
|
var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
|
||||||
|
|
||||||
|
var queryTranlations = new List<string>
|
||||||
|
{
|
||||||
|
movie.Title,
|
||||||
|
movie.OriginalTitle
|
||||||
|
};
|
||||||
|
|
||||||
|
//Add Translation of wanted languages to search query
|
||||||
|
foreach (var translation in translations.Where(a => wantedLanguages.Contains(a.Language)))
|
||||||
|
{
|
||||||
|
queryTranlations.Add(translation.Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.SceneTitles = queryTranlations.Distinct().ToList();
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,11 @@ public virtual IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var titleYearSearchQuery = string.Format("{0} {1}", searchCriteria.Movie.Title, searchCriteria.Movie.Year);
|
foreach (var queryTitle in searchCriteria.QueryTitles)
|
||||||
pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=name&query={0}", titleYearSearchQuery.Trim())));
|
{
|
||||||
|
var titleYearSearchQuery = string.Format("{0}+{1}", queryTitle, searchCriteria.Movie.Year);
|
||||||
|
pageableRequests.Add(GetRequest("search-torrents", string.Format("&type=name&query={0}", titleYearSearchQuery.Trim())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Indexers.Newznab
|
namespace NzbDrone.Core.Indexers.Newznab
|
||||||
{
|
{
|
||||||
@ -7,7 +7,6 @@ public class NewznabCapabilities
|
|||||||
public int DefaultPageSize { get; set; }
|
public int DefaultPageSize { get; set; }
|
||||||
public int MaxPageSize { get; set; }
|
public int MaxPageSize { get; set; }
|
||||||
public string[] SupportedSearchParameters { get; set; }
|
public string[] SupportedSearchParameters { get; set; }
|
||||||
public string[] SupportedTvSearchParameters { get; set; }
|
|
||||||
public string[] SupportedMovieSearchParameters { get; set; }
|
public string[] SupportedMovieSearchParameters { get; set; }
|
||||||
public bool SupportsAggregateIdSearch { get; set; }
|
public bool SupportsAggregateIdSearch { get; set; }
|
||||||
public List<NewznabCategory> Categories { get; set; }
|
public List<NewznabCategory> Categories { get; set; }
|
||||||
@ -18,7 +17,6 @@ public NewznabCapabilities()
|
|||||||
MaxPageSize = 100;
|
MaxPageSize = 100;
|
||||||
SupportedSearchParameters = new[] { "q" };
|
SupportedSearchParameters = new[] { "q" };
|
||||||
SupportedMovieSearchParameters = new[] { "q", "imdbid", "imdbtitle", "imdbyear" };
|
SupportedMovieSearchParameters = new[] { "q", "imdbid", "imdbtitle", "imdbyear" };
|
||||||
SupportedTvSearchParameters = new[] { "q", "rid", "season", "ep" }; // This should remain 'rid' for older newznab installs.
|
|
||||||
SupportsAggregateIdSearch = false;
|
SupportsAggregateIdSearch = false;
|
||||||
Categories = new List<NewznabCategory>();
|
Categories = new List<NewznabCategory>();
|
||||||
}
|
}
|
||||||
|
@ -118,17 +118,6 @@ private NewznabCapabilities ParseCapabilities(HttpResponse response)
|
|||||||
capabilities.SupportedSearchParameters = xmlBasicSearch.Attribute("supportedParams").Value.Split(',');
|
capabilities.SupportedSearchParameters = xmlBasicSearch.Attribute("supportedParams").Value.Split(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
var xmlTvSearch = xmlSearching.Element("tv-search");
|
|
||||||
if (xmlTvSearch == null || xmlTvSearch.Attribute("available").Value != "yes")
|
|
||||||
{
|
|
||||||
capabilities.SupportedTvSearchParameters = null;
|
|
||||||
}
|
|
||||||
else if (xmlTvSearch.Attribute("supportedParams") != null)
|
|
||||||
{
|
|
||||||
capabilities.SupportedTvSearchParameters = xmlTvSearch.Attribute("supportedParams").Value.Split(',');
|
|
||||||
capabilities.SupportsAggregateIdSearch = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var xmlMovieSearch = xmlSearching.Element("movie-search");
|
var xmlMovieSearch = xmlSearching.Element("movie-search");
|
||||||
if (xmlMovieSearch == null || xmlMovieSearch.Attribute("available").Value != "yes")
|
if (xmlMovieSearch == null || xmlMovieSearch.Attribute("available").Value != "yes")
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,18 @@ public NewznabRequestGenerator(INewznabCapabilitiesProvider capabilitiesProvider
|
|||||||
PageSize = 100;
|
PageSize = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SupportsMovieSearch
|
private bool SupportsSearch
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||||
|
|
||||||
|
return capabilities.SupportedSearchParameters != null &&
|
||||||
|
capabilities.SupportedSearchParameters.Contains("q");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SupportsImdbSearch
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -33,6 +44,27 @@ private bool SupportsMovieSearch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool SupportsTmdbSearch
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||||
|
|
||||||
|
return capabilities.SupportedMovieSearchParameters != null &&
|
||||||
|
capabilities.SupportedMovieSearchParameters.Contains("tmdbid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SupportsAggregatedIdSearch
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var capabilities = _capabilitiesProvider.GetCapabilities(Settings);
|
||||||
|
|
||||||
|
return capabilities.SupportsAggregateIdSearch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public virtual IndexerPageableRequestChain GetRecentRequests()
|
public virtual IndexerPageableRequestChain GetRecentRequests()
|
||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
@ -56,34 +88,68 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC
|
|||||||
{
|
{
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
if (!Settings.SearchByTitle && SupportsMovieSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace())
|
AddMovieIdPageableRequests(pageableRequests, MaxPages, Settings.Categories, searchCriteria);
|
||||||
|
|
||||||
|
return pageableRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddMovieIdPageableRequests(IndexerPageableRequestChain chain, int maxPages, IEnumerable<int> categories, SearchCriteriaBase searchCriteria)
|
||||||
|
{
|
||||||
|
var includeTmdbSearch = SupportsTmdbSearch && searchCriteria.Movie.TmdbId > 0;
|
||||||
|
var includeImdbSearch = SupportsImdbSearch && searchCriteria.Movie.ImdbId.IsNotNullOrWhiteSpace();
|
||||||
|
|
||||||
|
if (SupportsAggregatedIdSearch && (includeTmdbSearch || includeImdbSearch))
|
||||||
{
|
{
|
||||||
pageableRequests.Add(GetPagedRequests(MaxPages, Settings.Categories, "movie", $"&imdbid={searchCriteria.Movie.ImdbId.Substring(2)}"));
|
var ids = "";
|
||||||
|
|
||||||
|
if (includeTmdbSearch)
|
||||||
|
{
|
||||||
|
ids += "&tmdbid=" + searchCriteria.Movie.TmdbId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeImdbSearch)
|
||||||
|
{
|
||||||
|
ids += "&imdbid=" + searchCriteria.Movie.ImdbId.Substring(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.Add(GetPagedRequests(maxPages, categories, "movie", ids));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var altTitles = searchCriteria.Movie.AlternativeTitles.Take(5).Select(t => t.Title).ToList();
|
if (includeTmdbSearch)
|
||||||
altTitles.Add(searchCriteria.Movie.Title);
|
|
||||||
|
|
||||||
var realMaxPages = (int)MaxPages / altTitles.Count();
|
|
||||||
|
|
||||||
//pageableRequests.Add(GetPagedRequests(MaxPages - (altTitles.Count() * realMaxPages), Settings.Categories, "search", $"&q={searchTitle}%20{searchCriteria.Movie.Year}"));
|
|
||||||
|
|
||||||
//Also use alt titles for searching.
|
|
||||||
foreach (string altTitle in altTitles)
|
|
||||||
{
|
{
|
||||||
var searchAltTitle = System.Web.HttpUtility.UrlPathEncode(Parser.Parser.ReplaceGermanUmlauts(Parser.Parser.NormalizeTitle(altTitle)));
|
chain.Add(GetPagedRequests(maxPages,
|
||||||
var queryString = $"&q={searchAltTitle}";
|
categories,
|
||||||
if (!Settings.RemoveYear)
|
"movie",
|
||||||
{
|
string.Format("&tmdbid={0}", searchCriteria.Movie.TmdbId)));
|
||||||
queryString += $"%20{searchCriteria.Movie.Year}";
|
}
|
||||||
}
|
else if (includeImdbSearch)
|
||||||
|
{
|
||||||
pageableRequests.Add(GetPagedRequests(realMaxPages, Settings.Categories, "search", queryString));
|
chain.Add(GetPagedRequests(maxPages,
|
||||||
|
categories,
|
||||||
|
"movie",
|
||||||
|
string.Format("&imdbid={0}", searchCriteria.Movie.ImdbId.Substring(2))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageableRequests;
|
if (SupportsSearch)
|
||||||
|
{
|
||||||
|
chain.AddTier();
|
||||||
|
foreach (var queryTitle in searchCriteria.QueryTitles)
|
||||||
|
{
|
||||||
|
var searchQuery = queryTitle;
|
||||||
|
|
||||||
|
if (!Settings.RemoveYear)
|
||||||
|
{
|
||||||
|
searchQuery = string.Format("{0} {1}", searchQuery, searchCriteria.Movie.Year);
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.Add(GetPagedRequests(MaxPages,
|
||||||
|
Settings.Categories,
|
||||||
|
"movie",
|
||||||
|
string.Format("&q={0}", NewsnabifyTitle(searchQuery))));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, IEnumerable<int> categories, string searchType, string parameters)
|
private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, IEnumerable<int> categories, string searchType, string parameters)
|
||||||
@ -115,6 +181,11 @@ private IEnumerable<IndexerRequest> GetPagedRequests(int maxPages, IEnumerable<i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string NewsnabifyTitle(string title)
|
||||||
|
{
|
||||||
|
return title.Replace("+", "%20");
|
||||||
|
}
|
||||||
|
|
||||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -77,21 +77,6 @@ protected override ReleaseInfo ProcessItem(XElement item, ReleaseInfo releaseInf
|
|||||||
releaseInfo = base.ProcessItem(item, releaseInfo);
|
releaseInfo = base.ProcessItem(item, releaseInfo);
|
||||||
releaseInfo.ImdbId = GetImdbId(item);
|
releaseInfo.ImdbId = GetImdbId(item);
|
||||||
|
|
||||||
//// This shouldn't be needed with changes to the DownloadDecisionMaker
|
|
||||||
//var imdbMovieTitle = GetImdbTitle(item);
|
|
||||||
//var imdbYear = GetImdbYear(item);
|
|
||||||
|
|
||||||
//// Fun, lets try to add year to the releaseTitle for our foriegn friends :)
|
|
||||||
//// if (!releaseInfo.Title.ContainsIgnoreCase(imdbMovieTitle + "." + imdbYear))
|
|
||||||
//var isMatch = Regex.IsMatch(releaseInfo.Title, $@"^{imdbMovieTitle}.*{imdbYear}", RegexOptions.IgnoreCase);
|
|
||||||
//if (!isMatch)
|
|
||||||
//{
|
|
||||||
// if (imdbYear != 1900 && imdbMovieTitle != string.Empty)
|
|
||||||
// {
|
|
||||||
// // releaseInfo.Title = releaseInfo.Title.Replace(imdbMovieTitle, imdbMovieTitle + "." + imdbYear);
|
|
||||||
// releaseInfo.Title = Regex.Replace(releaseInfo.Title, imdbMovieTitle, imdbMovieTitle + "." + imdbYear, RegexOptions.IgnoreCase);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
return releaseInfo;
|
return releaseInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,13 +88,6 @@ public NewznabSettings()
|
|||||||
Type = FieldType.Checkbox)]
|
Type = FieldType.Checkbox)]
|
||||||
public bool RemoveYear { get; set; }
|
public bool RemoveYear { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(7,
|
|
||||||
Label = "Search by Title",
|
|
||||||
HelpText = "By default, Radarr will try to search by IMDB ID if your indexer supports that. However, some indexers are not very good at tagging their releases correctly, so you can force Radarr to search that indexer by title instead.",
|
|
||||||
Advanced = true,
|
|
||||||
Type = FieldType.Checkbox)]
|
|
||||||
public bool SearchByTitle { get; set; }
|
|
||||||
|
|
||||||
// Field 8 is used by TorznabSettings MinimumSeeders
|
// Field 8 is used by TorznabSettings MinimumSeeders
|
||||||
// If you need to add another field here, update TorznabSettings as well and this comment
|
// If you need to add another field here, update TorznabSettings as well and this comment
|
||||||
public virtual NzbDroneValidationResult Validate()
|
public virtual NzbDroneValidationResult Validate()
|
||||||
|
@ -58,7 +58,16 @@ private string PrepareQuery(string query)
|
|||||||
|
|
||||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||||
{
|
{
|
||||||
return new IndexerPageableRequestChain();
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
|
foreach (var queryTitle in searchCriteria.QueryTitles)
|
||||||
|
{
|
||||||
|
pageableRequests.Add(GetPagedRequests(MaxPages,
|
||||||
|
string.Format("&term={0}",
|
||||||
|
PrepareQuery(string.Format("{0} {1}", queryTitle, searchCriteria.Movie.Year)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||||
|
@ -26,6 +26,19 @@ public virtual IndexerPageableRequestChain GetRecentRequests()
|
|||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||||
|
{
|
||||||
|
var pageableRequests = new IndexerPageableRequestChain();
|
||||||
|
|
||||||
|
foreach (var queryTitle in searchCriteria.QueryTitles)
|
||||||
|
{
|
||||||
|
pageableRequests.Add(GetPagedRequests(string.Format("{0}",
|
||||||
|
queryTitle)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageableRequests;
|
||||||
|
}
|
||||||
|
|
||||||
private IEnumerable<IndexerRequest> GetPagedRequests(string query)
|
private IEnumerable<IndexerRequest> GetPagedRequests(string query)
|
||||||
{
|
{
|
||||||
var url = new StringBuilder();
|
var url = new StringBuilder();
|
||||||
@ -40,16 +53,6 @@ private IEnumerable<IndexerRequest> GetPagedRequests(string query)
|
|||||||
yield return new IndexerRequest(url.ToString(), HttpAccept.Rss);
|
yield return new IndexerRequest(url.ToString(), HttpAccept.Rss);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
|
||||||
{
|
|
||||||
var pageableRequests = new IndexerPageableRequestChain();
|
|
||||||
|
|
||||||
pageableRequests.Add(GetPagedRequests(string.Format("{0}",
|
|
||||||
searchCriteria.Movie.Title)));
|
|
||||||
|
|
||||||
return pageableRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,10 @@ public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchC
|
|||||||
}
|
}
|
||||||
else if (searchCriteria.Movie.Year > 0)
|
else if (searchCriteria.Movie.Year > 0)
|
||||||
{
|
{
|
||||||
pageableRequests.Add(GetRequest(string.Format("{0}&year={1}", searchCriteria.Movie.Title, searchCriteria.Movie.Year)));
|
foreach (var queryTitle in searchCriteria.QueryTitles)
|
||||||
|
{
|
||||||
|
pageableRequests.Add(GetRequest(string.Format("{0}&year={1}", queryTitle, searchCriteria.Movie.Year)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageableRequests;
|
return pageableRequests;
|
||||||
|
@ -25,37 +25,33 @@ public LocalMovie Aggregate(LocalMovie localMovie, bool otherFiles)
|
|||||||
|
|
||||||
languages.AddRange(localMovie.DownloadClientMovieInfo?.Languages ?? new List<Language>());
|
languages.AddRange(localMovie.DownloadClientMovieInfo?.Languages ?? new List<Language>());
|
||||||
|
|
||||||
if (!languages.Any(l => l != Language.English))
|
if (!languages.Any(l => l != Language.Unknown))
|
||||||
{
|
{
|
||||||
languages = localMovie.FolderMovieInfo?.Languages ?? new List<Language>();
|
languages = localMovie.FolderMovieInfo?.Languages ?? new List<Language>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!languages.Any(l => l != Language.English))
|
if (!languages.Any(l => l != Language.Unknown))
|
||||||
{
|
{
|
||||||
languages = localMovie.FileMovieInfo?.Languages ?? new List<Language>();
|
languages = localMovie.FileMovieInfo?.Languages ?? new List<Language>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!languages.Any())
|
if (!languages.Any())
|
||||||
{
|
{
|
||||||
languages.Add(Language.English);
|
languages.Add(Language.Unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
languages = languages.Distinct().ToList();
|
||||||
|
|
||||||
|
if (languages.Count == 1 && languages.Contains(Language.Unknown))
|
||||||
|
{
|
||||||
|
languages = new List<Language> { localMovie.Movie.OriginalLanguage };
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Using languages: {0}", languages.Select(l => l.Name).ToList().Join(","));
|
_logger.Debug("Using languages: {0}", languages.Select(l => l.Name).ToList().Join(","));
|
||||||
|
|
||||||
localMovie.Languages = languages.Distinct().ToList();
|
localMovie.Languages = languages;
|
||||||
|
|
||||||
return localMovie;
|
return localMovie;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Language> GetLanguage(ParsedMovieInfo parsedMovieInfo)
|
|
||||||
{
|
|
||||||
if (parsedMovieInfo == null)
|
|
||||||
{
|
|
||||||
// English is the default language when otherwise unknown
|
|
||||||
return new List<Language> { Language.English };
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedMovieInfo.Languages;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.Credits;
|
using NzbDrone.Core.Movies.Credits;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MetadataSource
|
namespace NzbDrone.Core.MetadataSource
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@ public class MovieResource
|
|||||||
public string ImdbId { get; set; }
|
public string ImdbId { get; set; }
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string OriginalTitle { get; set; }
|
||||||
public string TitleSlug { get; set; }
|
public string TitleSlug { get; set; }
|
||||||
public List<RatingResource> Ratings { get; set; }
|
public List<RatingResource> Ratings { get; set; }
|
||||||
public int? Runtime { get; set; }
|
public int? Runtime { get; set; }
|
||||||
|
@ -3,6 +3,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook.Resource
|
|||||||
public class TranslationResource
|
public class TranslationResource
|
||||||
{
|
{
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string Overview { get; set; }
|
||||||
public string Language { get; set; }
|
public string Language { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||||
using NzbDrone.Core.Movies.Credits;
|
using NzbDrone.Core.Movies.Credits;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.NetImport.TMDb;
|
using NzbDrone.Core.NetImport.TMDb;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
|
|
||||||
@ -29,11 +30,13 @@ public class SkyHookProxy : IProvideMovieInfo, ISearchForNewMovie
|
|||||||
private readonly IHttpRequestBuilderFactory _radarrMetadata;
|
private readonly IHttpRequestBuilderFactory _radarrMetadata;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly IMovieService _movieService;
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly IMovieTranslationService _movieTranslationService;
|
||||||
|
|
||||||
public SkyHookProxy(IHttpClient httpClient,
|
public SkyHookProxy(IHttpClient httpClient,
|
||||||
IRadarrCloudRequestBuilder requestBuilder,
|
IRadarrCloudRequestBuilder requestBuilder,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IMovieService movieService,
|
IMovieService movieService,
|
||||||
|
IMovieTranslationService movieTranslationService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
@ -41,6 +44,7 @@ public SkyHookProxy(IHttpClient httpClient,
|
|||||||
_radarrMetadata = requestBuilder.RadarrMetadata;
|
_radarrMetadata = requestBuilder.RadarrMetadata;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_movieService = movieService;
|
_movieService = movieService;
|
||||||
|
_movieTranslationService = movieTranslationService;
|
||||||
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@ -160,6 +164,7 @@ public Movie MapMovie(MovieResource resource)
|
|||||||
movie.TmdbId = resource.TmdbId;
|
movie.TmdbId = resource.TmdbId;
|
||||||
movie.ImdbId = resource.ImdbId;
|
movie.ImdbId = resource.ImdbId;
|
||||||
movie.Title = resource.Title;
|
movie.Title = resource.Title;
|
||||||
|
movie.OriginalTitle = resource.OriginalTitle;
|
||||||
movie.TitleSlug = resource.TitleSlug;
|
movie.TitleSlug = resource.TitleSlug;
|
||||||
movie.CleanTitle = resource.Title.CleanSeriesTitle();
|
movie.CleanTitle = resource.Title.CleanSeriesTitle();
|
||||||
movie.SortTitle = Parser.Parser.NormalizeTitle(resource.Title);
|
movie.SortTitle = Parser.Parser.NormalizeTitle(resource.Title);
|
||||||
@ -167,9 +172,14 @@ public Movie MapMovie(MovieResource resource)
|
|||||||
|
|
||||||
movie.AlternativeTitles.AddRange(resource.AlternativeTitles.Select(MapAlternativeTitle));
|
movie.AlternativeTitles.AddRange(resource.AlternativeTitles.Select(MapAlternativeTitle));
|
||||||
|
|
||||||
|
movie.Translations.AddRange(resource.Translations.Select(MapTranslation));
|
||||||
|
|
||||||
|
movie.OriginalLanguage = IsoLanguages.Find(resource.OriginalLanguage.ToLower())?.Language ?? Language.English;
|
||||||
|
|
||||||
movie.Website = resource.Homepage;
|
movie.Website = resource.Homepage;
|
||||||
movie.InCinemas = resource.InCinema;
|
movie.InCinemas = resource.InCinema;
|
||||||
movie.PhysicalRelease = resource.PhysicalRelease;
|
movie.PhysicalRelease = resource.PhysicalRelease;
|
||||||
|
movie.DigitalRelease = resource.DigitalRelease;
|
||||||
|
|
||||||
movie.Year = resource.Year;
|
movie.Year = resource.Year;
|
||||||
|
|
||||||
@ -195,44 +205,24 @@ public Movie MapMovie(MovieResource resource)
|
|||||||
|
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
|
|
||||||
//handle the case when we have both theatrical and physical release dates
|
movie.Status = MovieStatusType.Announced;
|
||||||
if (resource.InCinema.HasValue && resource.PhysicalRelease.HasValue)
|
|
||||||
{
|
|
||||||
if (now < resource.InCinema)
|
|
||||||
{
|
|
||||||
movie.Status = MovieStatusType.Announced;
|
|
||||||
}
|
|
||||||
else if (now >= resource.InCinema)
|
|
||||||
{
|
|
||||||
movie.Status = MovieStatusType.InCinemas;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (now >= resource.PhysicalRelease)
|
if (resource.InCinema.HasValue && now > resource.InCinema)
|
||||||
|
{
|
||||||
|
movie.Status = MovieStatusType.InCinemas;
|
||||||
|
|
||||||
|
if (!resource.PhysicalRelease.HasValue && !resource.DigitalRelease.HasValue && now > resource.InCinema.Value.AddDays(90))
|
||||||
{
|
{
|
||||||
movie.Status = MovieStatusType.Released;
|
movie.Status = MovieStatusType.Released;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle the case when we have theatrical release dates but we dont know the physical release date
|
if (resource.PhysicalRelease.HasValue && now >= resource.PhysicalRelease)
|
||||||
else if (resource.InCinema.HasValue && (now >= resource.InCinema))
|
|
||||||
{
|
|
||||||
movie.Status = MovieStatusType.InCinemas;
|
|
||||||
}
|
|
||||||
|
|
||||||
//handle the case where we only have a physical release date
|
|
||||||
else if ((resource.PhysicalRelease.HasValue && (now >= resource.PhysicalRelease)) || (resource.DigitalRelease.HasValue && (now >= resource.DigitalRelease)))
|
|
||||||
{
|
{
|
||||||
movie.Status = MovieStatusType.Released;
|
movie.Status = MovieStatusType.Released;
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise the title has only been announced
|
if (resource.DigitalRelease.HasValue && now >= resource.DigitalRelease)
|
||||||
else
|
|
||||||
{
|
|
||||||
movie.Status = MovieStatusType.Announced;
|
|
||||||
}
|
|
||||||
|
|
||||||
//since TMDB lacks alot of information lets assume that stuff is released if its been in cinemas for longer than 3 months.
|
|
||||||
if (!movie.PhysicalRelease.HasValue && (movie.Status == MovieStatusType.InCinemas) && (DateTime.Now.Subtract(movie.InCinemas.Value).TotalSeconds > 60 * 60 * 24 * 30 * 3))
|
|
||||||
{
|
{
|
||||||
movie.Status = MovieStatusType.Released;
|
movie.Status = MovieStatusType.Released;
|
||||||
}
|
}
|
||||||
@ -425,6 +415,10 @@ private Movie MapSearchResult(MovieResource result)
|
|||||||
{
|
{
|
||||||
movie = MapMovie(result);
|
movie = MapMovie(result);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movie.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
|
||||||
|
}
|
||||||
|
|
||||||
return movie;
|
return movie;
|
||||||
}
|
}
|
||||||
@ -474,6 +468,19 @@ private static AlternativeTitle MapAlternativeTitle(AlternativeTitleResource arg
|
|||||||
return newAlternativeTitle;
|
return newAlternativeTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static MovieTranslation MapTranslation(TranslationResource arg)
|
||||||
|
{
|
||||||
|
var newAlternativeTitle = new MovieTranslation
|
||||||
|
{
|
||||||
|
Title = arg.Title,
|
||||||
|
Overview = arg.Overview,
|
||||||
|
CleanTitle = arg.Title.CleanSeriesTitle(),
|
||||||
|
Language = IsoLanguages.Find(arg.Language.ToLower())?.Language
|
||||||
|
};
|
||||||
|
|
||||||
|
return newAlternativeTitle;
|
||||||
|
}
|
||||||
|
|
||||||
private static Ratings MapRatings(RatingResource rating)
|
private static Ratings MapRatings(RatingResource rating)
|
||||||
{
|
{
|
||||||
if (rating == null)
|
if (rating == null)
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Movies
|
namespace NzbDrone.Core.Movies
|
||||||
@ -16,7 +18,9 @@ public Movie()
|
|||||||
Genres = new List<string>();
|
Genres = new List<string>();
|
||||||
Tags = new HashSet<int>();
|
Tags = new HashSet<int>();
|
||||||
AlternativeTitles = new List<AlternativeTitle>();
|
AlternativeTitles = new List<AlternativeTitle>();
|
||||||
|
Translations = new List<MovieTranslation>();
|
||||||
Recommendations = new List<int>();
|
Recommendations = new List<int>();
|
||||||
|
OriginalLanguage = Language.English;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int TmdbId { get; set; }
|
public int TmdbId { get; set; }
|
||||||
@ -46,7 +50,7 @@ public Movie()
|
|||||||
public DateTime Added { get; set; }
|
public DateTime Added { get; set; }
|
||||||
public DateTime? InCinemas { get; set; }
|
public DateTime? InCinemas { get; set; }
|
||||||
public DateTime? PhysicalRelease { get; set; }
|
public DateTime? PhysicalRelease { get; set; }
|
||||||
public string PhysicalReleaseNote { get; set; }
|
public DateTime? DigitalRelease { get; set; }
|
||||||
public Profile Profile { get; set; }
|
public Profile Profile { get; set; }
|
||||||
public HashSet<int> Tags { get; set; }
|
public HashSet<int> Tags { get; set; }
|
||||||
public AddMovieOptions AddOptions { get; set; }
|
public AddMovieOptions AddOptions { get; set; }
|
||||||
@ -56,10 +60,12 @@ public Movie()
|
|||||||
|
|
||||||
//Get Loaded via a Join Query
|
//Get Loaded via a Join Query
|
||||||
public List<AlternativeTitle> AlternativeTitles { get; set; }
|
public List<AlternativeTitle> AlternativeTitles { get; set; }
|
||||||
|
public List<MovieTranslation> Translations { get; set; }
|
||||||
public int? SecondaryYear { get; set; }
|
public int? SecondaryYear { get; set; }
|
||||||
public int SecondaryYearSourceId { get; set; }
|
|
||||||
public string YouTubeTrailerId { get; set; }
|
public string YouTubeTrailerId { get; set; }
|
||||||
public string Studio { get; set; }
|
public string Studio { get; set; }
|
||||||
|
public string OriginalTitle { get; set; }
|
||||||
|
public Language OriginalLanguage { get; set; }
|
||||||
public List<int> Recommendations { get; set; }
|
public List<int> Recommendations { get; set; }
|
||||||
|
|
||||||
public bool IsRecentMovie
|
public bool IsRecentMovie
|
||||||
@ -122,7 +128,23 @@ public bool IsAvailable(int delay = 0)
|
|||||||
case MovieStatusType.Released:
|
case MovieStatusType.Released:
|
||||||
case MovieStatusType.PreDB:
|
case MovieStatusType.PreDB:
|
||||||
default:
|
default:
|
||||||
minimumAvailabilityDate = PhysicalRelease.HasValue ? PhysicalRelease.Value : (InCinemas.HasValue ? InCinemas.Value.AddDays(90) : DateTime.MaxValue);
|
if (PhysicalRelease.HasValue && DigitalRelease.HasValue)
|
||||||
|
{
|
||||||
|
minimumAvailabilityDate = new DateTime(Math.Min(PhysicalRelease.Value.Ticks, DigitalRelease.Value.Ticks));
|
||||||
|
}
|
||||||
|
else if (PhysicalRelease.HasValue)
|
||||||
|
{
|
||||||
|
minimumAvailabilityDate = PhysicalRelease.Value;
|
||||||
|
}
|
||||||
|
else if (DigitalRelease.HasValue)
|
||||||
|
{
|
||||||
|
minimumAvailabilityDate = DigitalRelease.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
minimumAvailabilityDate = InCinemas.HasValue ? InCinemas.Value.AddDays(90) : DateTime.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
using NzbDrone.Core.Movies.Commands;
|
using NzbDrone.Core.Movies.Commands;
|
||||||
using NzbDrone.Core.Movies.Credits;
|
using NzbDrone.Core.Movies.Credits;
|
||||||
using NzbDrone.Core.Movies.Events;
|
using NzbDrone.Core.Movies.Events;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Movies
|
namespace NzbDrone.Core.Movies
|
||||||
{
|
{
|
||||||
@ -22,6 +23,7 @@ public class RefreshMovieService : IExecute<RefreshMovieCommand>
|
|||||||
{
|
{
|
||||||
private readonly IProvideMovieInfo _movieInfo;
|
private readonly IProvideMovieInfo _movieInfo;
|
||||||
private readonly IMovieService _movieService;
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly IMovieTranslationService _movieTranslationService;
|
||||||
private readonly IAlternativeTitleService _titleService;
|
private readonly IAlternativeTitleService _titleService;
|
||||||
private readonly ICreditService _creditService;
|
private readonly ICreditService _creditService;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
@ -33,6 +35,7 @@ public class RefreshMovieService : IExecute<RefreshMovieCommand>
|
|||||||
|
|
||||||
public RefreshMovieService(IProvideMovieInfo movieInfo,
|
public RefreshMovieService(IProvideMovieInfo movieInfo,
|
||||||
IMovieService movieService,
|
IMovieService movieService,
|
||||||
|
IMovieTranslationService movieTranslationService,
|
||||||
IAlternativeTitleService titleService,
|
IAlternativeTitleService titleService,
|
||||||
ICreditService creditService,
|
ICreditService creditService,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
@ -43,6 +46,7 @@ public RefreshMovieService(IProvideMovieInfo movieInfo,
|
|||||||
{
|
{
|
||||||
_movieInfo = movieInfo;
|
_movieInfo = movieInfo;
|
||||||
_movieService = movieService;
|
_movieService = movieService;
|
||||||
|
_movieTranslationService = movieTranslationService;
|
||||||
_titleService = titleService;
|
_titleService = titleService;
|
||||||
_creditService = creditService;
|
_creditService = creditService;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
@ -104,8 +108,11 @@ private void RefreshMovieInfo(Movie movie)
|
|||||||
movie.Year = movieInfo.Year;
|
movie.Year = movieInfo.Year;
|
||||||
movie.SecondaryYear = movieInfo.SecondaryYear;
|
movie.SecondaryYear = movieInfo.SecondaryYear;
|
||||||
movie.PhysicalRelease = movieInfo.PhysicalRelease;
|
movie.PhysicalRelease = movieInfo.PhysicalRelease;
|
||||||
|
movie.DigitalRelease = movieInfo.DigitalRelease;
|
||||||
movie.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
|
movie.YouTubeTrailerId = movieInfo.YouTubeTrailerId;
|
||||||
movie.Studio = movieInfo.Studio;
|
movie.Studio = movieInfo.Studio;
|
||||||
|
movie.OriginalTitle = movieInfo.OriginalTitle;
|
||||||
|
movie.OriginalLanguage = movieInfo.OriginalLanguage;
|
||||||
movie.HasPreDBEntry = movieInfo.HasPreDBEntry;
|
movie.HasPreDBEntry = movieInfo.HasPreDBEntry;
|
||||||
movie.Recommendations = movieInfo.Recommendations;
|
movie.Recommendations = movieInfo.Recommendations;
|
||||||
|
|
||||||
@ -120,6 +127,7 @@ private void RefreshMovieInfo(Movie movie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
movie.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movie);
|
movie.AlternativeTitles = _titleService.UpdateTitles(movieInfo.AlternativeTitles, movie);
|
||||||
|
_movieTranslationService.UpdateTranslations(movieInfo.Translations, movie);
|
||||||
|
|
||||||
_movieService.UpdateMovie(new List<Movie> { movie }, true);
|
_movieService.UpdateMovie(new List<Movie> { movie }, true);
|
||||||
_creditService.UpdateCredits(credits, movie);
|
_creditService.UpdateCredits(credits, movie);
|
||||||
|
14
src/NzbDrone.Core/Movies/Translations/MovieTranslation.cs
Normal file
14
src/NzbDrone.Core/Movies/Translations/MovieTranslation.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Movies.Translations
|
||||||
|
{
|
||||||
|
public class MovieTranslation : ModelBase
|
||||||
|
{
|
||||||
|
public int MovieId { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string CleanTitle { get; set; }
|
||||||
|
public string Overview { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Movies.Translations
|
||||||
|
{
|
||||||
|
public interface IMovieTranslationRepository : IBasicRepository<MovieTranslation>
|
||||||
|
{
|
||||||
|
List<MovieTranslation> FindByMovieId(int movieId);
|
||||||
|
List<MovieTranslation> FindByLanguage(Language language);
|
||||||
|
void DeleteForMovies(List<int> movieIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MovieTranslationRepository : BasicRepository<MovieTranslation>, IMovieTranslationRepository
|
||||||
|
{
|
||||||
|
public MovieTranslationRepository(IMainDatabase database, IEventAggregator eventAggregator)
|
||||||
|
: base(database, eventAggregator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MovieTranslation> FindByMovieId(int movieId)
|
||||||
|
{
|
||||||
|
return Query(x => x.MovieId == movieId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MovieTranslation> FindByLanguage(Language language)
|
||||||
|
{
|
||||||
|
return Query(x => x.Language == language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteForMovies(List<int> movieIds)
|
||||||
|
{
|
||||||
|
Delete(x => movieIds.Contains(x.MovieId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Movies.Events;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Movies.Translations
|
||||||
|
{
|
||||||
|
public interface IMovieTranslationService
|
||||||
|
{
|
||||||
|
List<MovieTranslation> GetAllTranslationsForMovie(int movieId);
|
||||||
|
List<MovieTranslation> GetAllTranslationsForLanguage(Language language);
|
||||||
|
List<MovieTranslation> UpdateTranslations(List<MovieTranslation> titles, Movie movie);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MovieTranslationService : IMovieTranslationService, IHandleAsync<MoviesDeletedEvent>
|
||||||
|
{
|
||||||
|
private readonly IMovieTranslationRepository _translationRepo;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public MovieTranslationService(IMovieTranslationRepository translationRepo,
|
||||||
|
Logger logger)
|
||||||
|
{
|
||||||
|
_translationRepo = translationRepo;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MovieTranslation> GetAllTranslationsForMovie(int movieId)
|
||||||
|
{
|
||||||
|
return _translationRepo.FindByMovieId(movieId).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MovieTranslation> GetAllTranslationsForLanguage(Language language)
|
||||||
|
{
|
||||||
|
return _translationRepo.FindByLanguage(language).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveTitle(MovieTranslation title)
|
||||||
|
{
|
||||||
|
_translationRepo.Delete(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MovieTranslation> UpdateTranslations(List<MovieTranslation> translations, Movie movie)
|
||||||
|
{
|
||||||
|
int movieId = movie.Id;
|
||||||
|
|
||||||
|
// First update the movie ids so we can correlate them later
|
||||||
|
translations.ForEach(t => t.MovieId = movieId);
|
||||||
|
|
||||||
|
// Then throw out any we don't have languages for
|
||||||
|
translations = translations.Where(t => t.Language != null).ToList();
|
||||||
|
|
||||||
|
// Then make sure they are all distinct languages
|
||||||
|
translations = translations.DistinctBy(t => t.Language).ToList();
|
||||||
|
|
||||||
|
// Now find translations to delete, update and insert
|
||||||
|
var existingTranslations = _translationRepo.FindByMovieId(movieId);
|
||||||
|
|
||||||
|
translations.ForEach(c => c.Id = existingTranslations.FirstOrDefault(t => t.Language == c.Language)?.Id ?? 0);
|
||||||
|
|
||||||
|
var insert = translations.Where(t => t.Id == 0).ToList();
|
||||||
|
var update = translations.Where(t => t.Id > 0).ToList();
|
||||||
|
var delete = existingTranslations.Where(t => !translations.Any(c => c.Language == t.Language)).ToList();
|
||||||
|
|
||||||
|
_translationRepo.DeleteMany(delete.ToList());
|
||||||
|
_translationRepo.UpdateMany(update.ToList());
|
||||||
|
_translationRepo.InsertMany(insert.ToList());
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleAsync(MoviesDeletedEvent message)
|
||||||
|
{
|
||||||
|
_translationRepo.DeleteForMovies(message.Movies.Select(m => m.Id).ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,9 @@
|
|||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Organizer
|
namespace NzbDrone.Core.Organizer
|
||||||
@ -30,10 +33,11 @@ public class FileNameBuilder : IBuildFileNames
|
|||||||
private readonly INamingConfigService _namingConfigService;
|
private readonly INamingConfigService _namingConfigService;
|
||||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
private readonly IUpdateMediaInfo _mediaInfoUpdater;
|
private readonly IUpdateMediaInfo _mediaInfoUpdater;
|
||||||
|
private readonly IMovieTranslationService _movieTranslationService;
|
||||||
private readonly ICustomFormatService _formatService;
|
private readonly ICustomFormatService _formatService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9]+))?(?<suffix>[- ._)\]]*)\}",
|
private static readonly Regex TitleRegex = new Regex(@"\{(?<prefix>[- ._\[(]*)(?<token>(?:[a-z0-9]+)(?:(?<separator>[- ._]+)(?:[a-z0-9]+))?)(?::(?<customFormat>[a-z0-9|]+))?(?<suffix>[- ._)\]]*)\}",
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
private static readonly Regex TagsRegex = new Regex(@"(?<tags>\{tags(?:\:0+)?})",
|
private static readonly Regex TagsRegex = new Regex(@"(?<tags>\{tags(?:\:0+)?})",
|
||||||
@ -50,7 +54,7 @@ public class FileNameBuilder : IBuildFileNames
|
|||||||
public static readonly Regex SeriesTitleRegex = new Regex(@"(?<token>\{(?:Series)(?<separator>[- ._])(Clean)?Title\})",
|
public static readonly Regex SeriesTitleRegex = new Regex(@"(?<token>\{(?:Series)(?<separator>[- ._])(Clean)?Title\})",
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean)?(Title|Filename)(The)?)\})",
|
public static readonly Regex MovieTitleRegex = new Regex(@"(?<token>\{((?:(Movie|Original))(?<separator>[- ._])(Clean)?(Title|Filename)(The)?)(?::(?<customFormat>[a-z0-9]+))?\})",
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled);
|
private static readonly Regex FileNameCleanupRegex = new Regex(@"([- ._])(\1)+", RegexOptions.Compiled);
|
||||||
@ -69,12 +73,14 @@ public class FileNameBuilder : IBuildFileNames
|
|||||||
public FileNameBuilder(INamingConfigService namingConfigService,
|
public FileNameBuilder(INamingConfigService namingConfigService,
|
||||||
IQualityDefinitionService qualityDefinitionService,
|
IQualityDefinitionService qualityDefinitionService,
|
||||||
IUpdateMediaInfo mediaInfoUpdater,
|
IUpdateMediaInfo mediaInfoUpdater,
|
||||||
|
IMovieTranslationService movieTranslationService,
|
||||||
ICustomFormatService formatService,
|
ICustomFormatService formatService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_namingConfigService = namingConfigService;
|
_namingConfigService = namingConfigService;
|
||||||
_qualityDefinitionService = qualityDefinitionService;
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
_mediaInfoUpdater = mediaInfoUpdater;
|
_mediaInfoUpdater = mediaInfoUpdater;
|
||||||
|
_movieTranslationService = movieTranslationService;
|
||||||
_formatService = formatService;
|
_formatService = formatService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@ -86,7 +92,7 @@ public string BuildFileName(Movie movie, MovieFile movieFile, NamingConfig namin
|
|||||||
namingConfig = _namingConfigService.GetConfig();
|
namingConfig = _namingConfigService.GetConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!namingConfig.RenameEpisodes)
|
if (!namingConfig.RenameMovies)
|
||||||
{
|
{
|
||||||
return GetOriginalTitle(movieFile);
|
return GetOriginalTitle(movieFile);
|
||||||
}
|
}
|
||||||
@ -226,13 +232,40 @@ public static string CleanFolderName(string name)
|
|||||||
|
|
||||||
private void AddMovieTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Movie movie)
|
private void AddMovieTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, Movie movie)
|
||||||
{
|
{
|
||||||
tokenHandlers["{Movie Title}"] = m => movie.Title;
|
tokenHandlers["{Movie Title}"] = m => GetLanguageTitle(movie, m.CustomFormat);
|
||||||
tokenHandlers["{Movie CleanTitle}"] = m => CleanTitle(movie.Title);
|
tokenHandlers["{Movie CleanTitle}"] = m => CleanTitle(GetLanguageTitle(movie, m.CustomFormat));
|
||||||
tokenHandlers["{Movie Title The}"] = m => TitleThe(movie.Title);
|
tokenHandlers["{Movie Title The}"] = m => TitleThe(movie.Title);
|
||||||
tokenHandlers["{Movie Certification}"] = mbox => movie.Certification;
|
tokenHandlers["{Movie Certification}"] = mbox => movie.Certification;
|
||||||
tokenHandlers["{Movie TitleFirstCharacter}"] = m => TitleThe(movie.Title).Substring(0, 1).FirstCharToUpper();
|
tokenHandlers["{Movie TitleFirstCharacter}"] = m => TitleThe(movie.Title).Substring(0, 1).FirstCharToUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetLanguageTitle(Movie movie, string isoCodes)
|
||||||
|
{
|
||||||
|
if (isoCodes.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
foreach (var isoCode in isoCodes.Split('|'))
|
||||||
|
{
|
||||||
|
var language = IsoLanguages.Find(isoCode.ToLower())?.Language;
|
||||||
|
|
||||||
|
if (language == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var titles = movie.Translations.Where(t => t.Language == language).ToList();
|
||||||
|
|
||||||
|
if (!movie.Translations.Any())
|
||||||
|
{
|
||||||
|
titles = _movieTranslationService.GetAllTranslationsForMovie(movie.Id).Where(t => t.Language == language).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return titles.FirstOrDefault()?.Title ?? movie.Title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return movie.Title;
|
||||||
|
}
|
||||||
|
|
||||||
private void AddTagsTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile movieFile)
|
private void AddTagsTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile movieFile)
|
||||||
{
|
{
|
||||||
if (movieFile.Edition.IsNotNullOrWhiteSpace())
|
if (movieFile.Edition.IsNotNullOrWhiteSpace())
|
||||||
|
@ -6,15 +6,15 @@ public class NamingConfig : ModelBase
|
|||||||
{
|
{
|
||||||
public static NamingConfig Default => new NamingConfig
|
public static NamingConfig Default => new NamingConfig
|
||||||
{
|
{
|
||||||
RenameEpisodes = false,
|
RenameMovies = false,
|
||||||
ReplaceIllegalCharacters = true,
|
ReplaceIllegalCharacters = true,
|
||||||
ColonReplacementFormat = 0,
|
ColonReplacementFormat = 0,
|
||||||
MultiEpisodeStyle = 0,
|
MultiEpisodeStyle = 0,
|
||||||
MovieFolderFormat = "{Movie Title} ({Release Year})",
|
MovieFolderFormat = "{Movie Title:EN} ({Release Year})",
|
||||||
StandardMovieFormat = "{Movie Title} ({Release Year}) {Quality Full}",
|
StandardMovieFormat = "{Movie Title:EN} ({Release Year}) {Quality Full}",
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool RenameEpisodes { get; set; }
|
public bool RenameMovies { get; set; }
|
||||||
public bool ReplaceIllegalCharacters { get; set; }
|
public bool ReplaceIllegalCharacters { get; set; }
|
||||||
public ColonReplacementFormat ColonReplacementFormat { get; set; }
|
public ColonReplacementFormat ColonReplacementFormat { get; set; }
|
||||||
public int MultiEpisodeStyle { get; set; }
|
public int MultiEpisodeStyle { get; set; }
|
||||||
|
@ -14,7 +14,7 @@ public static class LanguageParser
|
|||||||
{
|
{
|
||||||
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(LanguageParser));
|
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(LanguageParser));
|
||||||
|
|
||||||
private static readonly Regex LanguageRegex = new Regex(@"(?:\W|_|^)(?<italian>\b(?:ita|italian)\b)|(?<german>german\b|videomann)|(?<flemish>flemish)|(?<greek>greek)|(?<french>(?:\W|_)(?:FR|VOSTFR|VO|VFF|VFQ|VFI|VF2|TRUEFRENCH)(?:\W|_))|(?<russian>\brus\b)|(?<dutch>nl\W?subs?)|(?<hungarian>\b(?:HUNDUB|HUN)\b)|(?<hebrew>\bHebDub\b)",
|
private static readonly Regex LanguageRegex = new Regex(@"(?:\W|_|^)(?<italian>\b(?:ita|italian)\b)|(?<german>\b(?:german|videomann|ger)\b)|(?<flemish>flemish)|(?<greek>greek)|(?<french>(?:\W|_)(?:FR|VOSTFR|VO|VFF|VFQ|VFI|VF2|TRUEFRENCH)(?:\W|_))|(?<russian>\brus\b)|(?<english>\beng\b)|(?<dutch>nl\W?subs?)|(?<hungarian>\b(?:HUNDUB|HUN)\b)|(?<hebrew>\bHebDub\b)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Regex CaseSensitiveLanguageRegex = new Regex(@"(?<lithuanian>\bLT\b)|(?<czech>\bCZ\b)",
|
private static readonly Regex CaseSensitiveLanguageRegex = new Regex(@"(?<lithuanian>\bLT\b)|(?<czech>\bCZ\b)",
|
||||||
@ -140,51 +140,59 @@ public static List<Language> ParseLanguages(string title)
|
|||||||
languages.Add(Language.Czech);
|
languages.Add(Language.Czech);
|
||||||
}
|
}
|
||||||
|
|
||||||
var match = LanguageRegex.Match(title);
|
var matches = LanguageRegex.Matches(title);
|
||||||
|
|
||||||
if (match.Groups["italian"].Captures.Cast<Capture>().Any())
|
foreach (Match match in matches)
|
||||||
{
|
{
|
||||||
languages.Add(Language.Italian);
|
if (match.Groups["italian"].Captures.Cast<Capture>().Any())
|
||||||
}
|
{
|
||||||
|
languages.Add(Language.Italian);
|
||||||
|
}
|
||||||
|
|
||||||
if (match.Groups["german"].Captures.Cast<Capture>().Any())
|
if (match.Groups["german"].Captures.Cast<Capture>().Any())
|
||||||
{
|
{
|
||||||
languages.Add(Language.German);
|
languages.Add(Language.German);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["flemish"].Captures.Cast<Capture>().Any())
|
if (match.Groups["flemish"].Captures.Cast<Capture>().Any())
|
||||||
{
|
{
|
||||||
languages.Add(Language.Flemish);
|
languages.Add(Language.Flemish);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["greek"].Captures.Cast<Capture>().Any())
|
if (match.Groups["greek"].Captures.Cast<Capture>().Any())
|
||||||
{
|
{
|
||||||
languages.Add(Language.Greek);
|
languages.Add(Language.Greek);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["french"].Success)
|
if (match.Groups["french"].Success)
|
||||||
{
|
{
|
||||||
languages.Add(Language.French);
|
languages.Add(Language.French);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["russian"].Success)
|
if (match.Groups["russian"].Success)
|
||||||
{
|
{
|
||||||
languages.Add(Language.Russian);
|
languages.Add(Language.Russian);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["dutch"].Success)
|
if (match.Groups["english"].Success)
|
||||||
{
|
{
|
||||||
languages.Add(Language.Dutch);
|
languages.Add(Language.English);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["hungarian"].Success)
|
if (match.Groups["dutch"].Success)
|
||||||
{
|
{
|
||||||
languages.Add(Language.Hungarian);
|
languages.Add(Language.Dutch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match.Groups["hebrew"].Success)
|
if (match.Groups["hungarian"].Success)
|
||||||
{
|
{
|
||||||
languages.Add(Language.Hebrew);
|
languages.Add(Language.Hungarian);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.Groups["hebrew"].Success)
|
||||||
|
{
|
||||||
|
languages.Add(Language.Hebrew);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title.ToLower().Contains("multi"))
|
if (title.ToLower().Contains("multi"))
|
||||||
@ -198,7 +206,7 @@ public static List<Language> ParseLanguages(string title)
|
|||||||
|
|
||||||
if (!languages.Any())
|
if (!languages.Any())
|
||||||
{
|
{
|
||||||
languages.Add(Language.English);
|
languages.Add(Language.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
return languages.DistinctBy(l => (int)l).ToList();
|
return languages.DistinctBy(l => (int)l).ToList();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.AlternativeTitles;
|
using NzbDrone.Core.Movies.AlternativeTitles;
|
||||||
using NzbDrone.Core.Parser.Augmenters;
|
using NzbDrone.Core.Parser.Augmenters;
|
||||||
@ -141,6 +142,12 @@ public MappingResult Map(ParsedMovieInfo parsedMovieInfo, string imdbId, SearchC
|
|||||||
result.Movie = null;
|
result.Movie = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Use movie language as fallback if we could't parse a language (more accurate than just using English)
|
||||||
|
if (parsedMovieInfo.Languages.Count <= 1 && parsedMovieInfo.Languages.First() == Language.Unknown && result.Movie != null)
|
||||||
|
{
|
||||||
|
parsedMovieInfo.Languages = new List<Language> { result.Movie.OriginalLanguage };
|
||||||
|
}
|
||||||
|
|
||||||
result.RemoteMovie.ParsedMovieInfo = parsedMovieInfo;
|
result.RemoteMovie.ParsedMovieInfo = parsedMovieInfo;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -21,6 +21,7 @@ public interface IProfileService
|
|||||||
Profile Get(int id);
|
Profile Get(int id);
|
||||||
bool Exists(int id);
|
bool Exists(int id);
|
||||||
Profile GetDefaultProfile(string name, Quality cutoff = null, params Quality[] allowed);
|
Profile GetDefaultProfile(string name, Quality cutoff = null, params Quality[] allowed);
|
||||||
|
List<Language> GetAcceptableLanguages(int profileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ProfileService : IProfileService,
|
public class ProfileService : IProfileService,
|
||||||
@ -265,6 +266,24 @@ public Profile GetDefaultProfile(string name, Quality cutoff = null, params Qual
|
|||||||
return qualityProfile;
|
return qualityProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Language> GetAcceptableLanguages(int profileId)
|
||||||
|
{
|
||||||
|
var profile = Get(profileId);
|
||||||
|
|
||||||
|
var wantedTitleLanguages = profile.FormatItems.Where(i => i.Score > 0).Select(item => item.Format)
|
||||||
|
.SelectMany(format => format.Specifications)
|
||||||
|
.Where(specification => specification is LanguageSpecification && !specification.Negate)
|
||||||
|
.Cast<LanguageSpecification>()
|
||||||
|
.Where(specification => specification.Value > 0)
|
||||||
|
.Select(specification => (Language)specification.Value)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
wantedTitleLanguages.Add(profile.Language);
|
||||||
|
|
||||||
|
return wantedTitleLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
private Profile AddDefaultProfile(string name, Quality cutoff, params Quality[] allowed)
|
private Profile AddDefaultProfile(string name, Quality cutoff, params Quality[] allowed)
|
||||||
{
|
{
|
||||||
var profile = GetDefaultProfile(name, cutoff, allowed);
|
var profile = GetDefaultProfile(name, cutoff, allowed);
|
||||||
|
@ -123,9 +123,7 @@ private void CreateEvent(Ical.Net.Calendar calendar, Movie movie, bool cinemasRe
|
|||||||
occurrence.Description = movie.Overview;
|
occurrence.Description = movie.Overview;
|
||||||
occurrence.Categories = new List<string>() { movie.Studio };
|
occurrence.Categories = new List<string>() { movie.Studio };
|
||||||
|
|
||||||
var physicalText = movie.PhysicalReleaseNote.IsNotNullOrWhiteSpace()
|
var physicalText = "(Physical Release)";
|
||||||
? $"(Physical Release, {movie.PhysicalReleaseNote})"
|
|
||||||
: "(Physical Release)";
|
|
||||||
occurrence.Summary = $"{movie.Title} " + (cinemasRelease ? "(Theatrical Release)" : physicalText);
|
occurrence.Summary = $"{movie.Title} " + (cinemasRelease ? "(Theatrical Release)" : physicalText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
using Radarr.Api.V3.Movies;
|
using Radarr.Api.V3.Movies;
|
||||||
using Radarr.Http;
|
using Radarr.Http;
|
||||||
@ -13,15 +16,21 @@ namespace Radarr.Api.V3.Calendar
|
|||||||
public class CalendarModule : RadarrRestModuleWithSignalR<MovieResource, Movie>
|
public class CalendarModule : RadarrRestModuleWithSignalR<MovieResource, Movie>
|
||||||
{
|
{
|
||||||
private readonly IMovieService _moviesService;
|
private readonly IMovieService _moviesService;
|
||||||
|
private readonly IMovieTranslationService _movieTranslationService;
|
||||||
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
|
||||||
public CalendarModule(IBroadcastSignalRMessage signalR,
|
public CalendarModule(IBroadcastSignalRMessage signalR,
|
||||||
IMovieService moviesService,
|
IMovieService moviesService,
|
||||||
IUpgradableSpecification qualityUpgradableSpecification)
|
IMovieTranslationService movieTranslationService,
|
||||||
|
IUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IConfigService configService)
|
||||||
: base(signalR, "calendar")
|
: base(signalR, "calendar")
|
||||||
{
|
{
|
||||||
_moviesService = moviesService;
|
_moviesService = moviesService;
|
||||||
|
_movieTranslationService = movieTranslationService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||||
|
_configService = configService;
|
||||||
|
|
||||||
GetResourceAll = GetCalendar;
|
GetResourceAll = GetCalendar;
|
||||||
}
|
}
|
||||||
@ -63,7 +72,8 @@ protected MovieResource MapToResource(Movie movie)
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resource = movie.ToResource(_qualityUpgradableSpecification);
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(movie.Id).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
var resource = movie.ToResource(_qualityUpgradableSpecification, translation);
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public static NamingConfigResource ToResource(this NamingConfig model)
|
|||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
|
|
||||||
RenameMovies = model.RenameEpisodes,
|
RenameMovies = model.RenameMovies,
|
||||||
ReplaceIllegalCharacters = model.ReplaceIllegalCharacters,
|
ReplaceIllegalCharacters = model.ReplaceIllegalCharacters,
|
||||||
ColonReplacementFormat = model.ColonReplacementFormat,
|
ColonReplacementFormat = model.ColonReplacementFormat,
|
||||||
StandardMovieFormat = model.StandardMovieFormat,
|
StandardMovieFormat = model.StandardMovieFormat,
|
||||||
@ -43,7 +43,7 @@ public static NamingConfig ToModel(this NamingConfigResource resource)
|
|||||||
{
|
{
|
||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
|
|
||||||
RenameEpisodes = resource.RenameMovies,
|
RenameMovies = resource.RenameMovies,
|
||||||
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
||||||
ColonReplacementFormat = resource.ColonReplacementFormat,
|
ColonReplacementFormat = resource.ColonReplacementFormat,
|
||||||
StandardMovieFormat = resource.StandardMovieFormat,
|
StandardMovieFormat = resource.StandardMovieFormat,
|
||||||
|
@ -16,6 +16,7 @@ public class UiConfigResource : RestResource
|
|||||||
public bool ShowRelativeDates { get; set; }
|
public bool ShowRelativeDates { get; set; }
|
||||||
|
|
||||||
public bool EnableColorImpairedMode { get; set; }
|
public bool EnableColorImpairedMode { get; set; }
|
||||||
|
public int MovieInfoLanguage { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UiConfigResourceMapper
|
public static class UiConfigResourceMapper
|
||||||
@ -33,6 +34,7 @@ public static UiConfigResource ToResource(IConfigService model)
|
|||||||
ShowRelativeDates = model.ShowRelativeDates,
|
ShowRelativeDates = model.ShowRelativeDates,
|
||||||
|
|
||||||
EnableColorImpairedMode = model.EnableColorImpairedMode,
|
EnableColorImpairedMode = model.EnableColorImpairedMode,
|
||||||
|
MovieInfoLanguage = model.MovieInfoLanguage
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,7 @@ public static ManualImportResource ToResource(this ManualImportItem model)
|
|||||||
Id = HashConverter.GetHashInt31(model.Path),
|
Id = HashConverter.GetHashInt31(model.Path),
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
RelativePath = model.RelativePath,
|
RelativePath = model.RelativePath,
|
||||||
|
FolderName = model.FolderName,
|
||||||
// FolderName = model.FolderName,
|
|
||||||
Name = model.Name,
|
Name = model.Name,
|
||||||
Size = model.Size,
|
Size = model.Size,
|
||||||
Movie = model.Movie.ToResource(),
|
Movie = model.Movie.ToResource(),
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.MetadataSource;
|
using NzbDrone.Core.MetadataSource;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
@ -15,13 +17,18 @@ public class MovieLookupModule : RadarrRestModule<MovieResource>
|
|||||||
private readonly ISearchForNewMovie _searchProxy;
|
private readonly ISearchForNewMovie _searchProxy;
|
||||||
private readonly IProvideMovieInfo _movieInfo;
|
private readonly IProvideMovieInfo _movieInfo;
|
||||||
private readonly IBuildFileNames _fileNameBuilder;
|
private readonly IBuildFileNames _fileNameBuilder;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
|
||||||
public MovieLookupModule(ISearchForNewMovie searchProxy, IProvideMovieInfo movieInfo, IBuildFileNames fileNameBuilder)
|
public MovieLookupModule(ISearchForNewMovie searchProxy,
|
||||||
|
IProvideMovieInfo movieInfo,
|
||||||
|
IBuildFileNames fileNameBuilder,
|
||||||
|
IConfigService configService)
|
||||||
: base("/movie/lookup")
|
: base("/movie/lookup")
|
||||||
{
|
{
|
||||||
_movieInfo = movieInfo;
|
_movieInfo = movieInfo;
|
||||||
_searchProxy = searchProxy;
|
_searchProxy = searchProxy;
|
||||||
_fileNameBuilder = fileNameBuilder;
|
_fileNameBuilder = fileNameBuilder;
|
||||||
|
_configService = configService;
|
||||||
Get("/", x => Search());
|
Get("/", x => Search());
|
||||||
Get("/tmdb", x => SearchByTmdbId());
|
Get("/tmdb", x => SearchByTmdbId());
|
||||||
Get("/imdb", x => SearchByImdbId());
|
Get("/imdb", x => SearchByImdbId());
|
||||||
@ -33,7 +40,8 @@ private object SearchByTmdbId()
|
|||||||
if (int.TryParse(Request.Query.tmdbId, out tmdbId))
|
if (int.TryParse(Request.Query.tmdbId, out tmdbId))
|
||||||
{
|
{
|
||||||
var result = _movieInfo.GetMovieInfo(tmdbId).Item1;
|
var result = _movieInfo.GetMovieInfo(tmdbId).Item1;
|
||||||
return result.ToResource();
|
var translation = result.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
return result.ToResource(translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new BadRequestException("Tmdb Id was not valid");
|
throw new BadRequestException("Tmdb Id was not valid");
|
||||||
@ -43,20 +51,24 @@ private object SearchByImdbId()
|
|||||||
{
|
{
|
||||||
string imdbId = Request.Query.imdbId;
|
string imdbId = Request.Query.imdbId;
|
||||||
var result = _movieInfo.GetMovieByImdbId(imdbId);
|
var result = _movieInfo.GetMovieByImdbId(imdbId);
|
||||||
return result.ToResource();
|
|
||||||
|
var translation = result.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
return result.ToResource(translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private object Search()
|
private object Search()
|
||||||
{
|
{
|
||||||
var imdbResults = _searchProxy.SearchForNewMovie((string)Request.Query.term);
|
var searchResults = _searchProxy.SearchForNewMovie((string)Request.Query.term);
|
||||||
return MapToResource(imdbResults);
|
|
||||||
|
return MapToResource(searchResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<MovieResource> MapToResource(IEnumerable<Movie> movies)
|
private IEnumerable<MovieResource> MapToResource(IEnumerable<Movie> movies)
|
||||||
{
|
{
|
||||||
foreach (var currentMovie in movies)
|
foreach (var currentMovie in movies)
|
||||||
{
|
{
|
||||||
var resource = currentMovie.ToResource();
|
var translation = currentMovie.Translations.FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
var resource = currentMovie.ToResource(translation);
|
||||||
var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||||
if (poster != null)
|
if (poster != null)
|
||||||
{
|
{
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Datastore.Events;
|
using NzbDrone.Core.Datastore.Events;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
@ -12,6 +15,7 @@
|
|||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
using NzbDrone.Core.Movies.Commands;
|
using NzbDrone.Core.Movies.Commands;
|
||||||
using NzbDrone.Core.Movies.Events;
|
using NzbDrone.Core.Movies.Events;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.Core.Validation.Paths;
|
using NzbDrone.Core.Validation.Paths;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
@ -30,17 +34,21 @@ public class MovieModule : RadarrRestModuleWithSignalR<MovieResource, Movie>,
|
|||||||
IHandle<MediaCoversUpdatedEvent>
|
IHandle<MediaCoversUpdatedEvent>
|
||||||
{
|
{
|
||||||
private readonly IMovieService _moviesService;
|
private readonly IMovieService _moviesService;
|
||||||
|
private readonly IMovieTranslationService _movieTranslationService;
|
||||||
private readonly IAddMovieService _addMovieService;
|
private readonly IAddMovieService _addMovieService;
|
||||||
private readonly IMapCoversToLocal _coverMapper;
|
private readonly IMapCoversToLocal _coverMapper;
|
||||||
private readonly IManageCommandQueue _commandQueueManager;
|
private readonly IManageCommandQueue _commandQueueManager;
|
||||||
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly IUpgradableSpecification _qualityUpgradableSpecification;
|
||||||
|
private readonly IConfigService _configService;
|
||||||
|
|
||||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
IMovieService moviesService,
|
IMovieService moviesService,
|
||||||
|
IMovieTranslationService movieTranslationService,
|
||||||
IAddMovieService addMovieService,
|
IAddMovieService addMovieService,
|
||||||
IMapCoversToLocal coverMapper,
|
IMapCoversToLocal coverMapper,
|
||||||
IManageCommandQueue commandQueueManager,
|
IManageCommandQueue commandQueueManager,
|
||||||
IUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IConfigService configService,
|
||||||
RootFolderValidator rootFolderValidator,
|
RootFolderValidator rootFolderValidator,
|
||||||
MappedNetworkDriveValidator mappedNetworkDriveValidator,
|
MappedNetworkDriveValidator mappedNetworkDriveValidator,
|
||||||
MoviePathValidator moviesPathValidator,
|
MoviePathValidator moviesPathValidator,
|
||||||
@ -52,8 +60,10 @@ public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
|||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
_moviesService = moviesService;
|
_moviesService = moviesService;
|
||||||
|
_movieTranslationService = movieTranslationService;
|
||||||
_addMovieService = addMovieService;
|
_addMovieService = addMovieService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||||
|
_configService = configService;
|
||||||
_coverMapper = coverMapper;
|
_coverMapper = coverMapper;
|
||||||
_commandQueueManager = commandQueueManager;
|
_commandQueueManager = commandQueueManager;
|
||||||
|
|
||||||
@ -95,33 +105,44 @@ private List<MovieResource> AllMovie()
|
|||||||
|
|
||||||
if (tmdbId > 0)
|
if (tmdbId > 0)
|
||||||
{
|
{
|
||||||
moviesResources.AddIfNotNull(_moviesService.FindByTmdbId(tmdbId).ToResource(_qualityUpgradableSpecification));
|
var movie = _moviesService.FindByTmdbId(tmdbId);
|
||||||
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(movie.Id).Where(t => t.Language == (Language)_configService.MovieInfoLanguage).FirstOrDefault();
|
||||||
|
|
||||||
|
moviesResources.AddIfNotNull(movie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
moviesResources.AddRange(_moviesService.GetAllMovies().ToResource(_qualityUpgradableSpecification));
|
var translations = _movieTranslationService.GetAllTranslationsForLanguage((Language)_configService.MovieInfoLanguage);
|
||||||
|
var movies = _moviesService.GetAllMovies();
|
||||||
|
|
||||||
|
foreach (var movie in movies)
|
||||||
|
{
|
||||||
|
var translation = translations.FirstOrDefault(t => t.MovieId == movie.Id);
|
||||||
|
moviesResources.Add(movie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapCoversToLocal(moviesResources.ToArray());
|
MapCoversToLocal(moviesResources.ToArray());
|
||||||
PopulateAlternateTitles(moviesResources);
|
|
||||||
|
|
||||||
return moviesResources;
|
return moviesResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MovieResource GetMovie(int id)
|
private MovieResource GetMovie(int id)
|
||||||
{
|
{
|
||||||
var movies = _moviesService.GetMovie(id);
|
var movie = _moviesService.GetMovie(id);
|
||||||
return MapToResource(movies);
|
return MapToResource(movie);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MovieResource MapToResource(Movie movies)
|
protected MovieResource MapToResource(Movie movie)
|
||||||
{
|
{
|
||||||
if (movies == null)
|
if (movie == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resource = movies.ToResource();
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(movie.Id).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
|
||||||
|
var resource = movie.ToResource(_qualityUpgradableSpecification, translation);
|
||||||
MapCoversToLocal(resource);
|
MapCoversToLocal(resource);
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
@ -155,9 +176,10 @@ private void UpdateMovie(MovieResource moviesResource)
|
|||||||
|
|
||||||
var model = moviesResource.ToModel(movie);
|
var model = moviesResource.ToModel(movie);
|
||||||
|
|
||||||
_moviesService.UpdateMovie(model);
|
var updatedMovie = _moviesService.UpdateMovie(model);
|
||||||
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(updatedMovie.Id).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
|
||||||
BroadcastResourceChange(ModelAction.Updated, moviesResource);
|
BroadcastResourceChange(ModelAction.Updated, updatedMovie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteMovie(int id)
|
private void DeleteMovie(int id)
|
||||||
@ -176,28 +198,10 @@ private void MapCoversToLocal(params MovieResource[] movies)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateAlternateTitles(List<MovieResource> resources)
|
|
||||||
{
|
|
||||||
foreach (var resource in resources)
|
|
||||||
{
|
|
||||||
PopulateAlternateTitles(resource);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PopulateAlternateTitles(MovieResource resource)
|
|
||||||
{
|
|
||||||
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
|
||||||
|
|
||||||
//if (mappings == null) return;
|
|
||||||
|
|
||||||
//Not necessary anymore
|
|
||||||
|
|
||||||
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(MovieImportedEvent message)
|
public void Handle(MovieImportedEvent message)
|
||||||
{
|
{
|
||||||
BroadcastResourceChange(ModelAction.Updated, message.ImportedMovie.MovieId);
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(message.ImportedMovie.MovieId).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.ImportedMovie.Movie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(MovieFileDeletedEvent message)
|
public void Handle(MovieFileDeletedEvent message)
|
||||||
@ -212,12 +216,14 @@ public void Handle(MovieFileDeletedEvent message)
|
|||||||
|
|
||||||
public void Handle(MovieUpdatedEvent message)
|
public void Handle(MovieUpdatedEvent message)
|
||||||
{
|
{
|
||||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(message.Movie.Id).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(MovieEditedEvent message)
|
public void Handle(MovieEditedEvent message)
|
||||||
{
|
{
|
||||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(message.Movie.Id).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(MoviesDeletedEvent message)
|
public void Handle(MoviesDeletedEvent message)
|
||||||
@ -230,7 +236,8 @@ public void Handle(MoviesDeletedEvent message)
|
|||||||
|
|
||||||
public void Handle(MovieRenamedEvent message)
|
public void Handle(MovieRenamedEvent message)
|
||||||
{
|
{
|
||||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
var translation = _movieTranslationService.GetAllTranslationsForMovie(message.Movie.Id).FirstOrDefault(t => t.Language == (Language)_configService.MovieInfoLanguage);
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.ToResource(_qualityUpgradableSpecification, translation));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Handle(MediaCoversUpdatedEvent message)
|
public void Handle(MediaCoversUpdatedEvent message)
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.Movies;
|
using NzbDrone.Core.Movies;
|
||||||
|
using NzbDrone.Core.Movies.Translations;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
using Radarr.Api.V3.MovieFiles;
|
using Radarr.Api.V3.MovieFiles;
|
||||||
using Radarr.Http.REST;
|
using Radarr.Http.REST;
|
||||||
|
|
||||||
@ -22,6 +25,7 @@ public MovieResource()
|
|||||||
|
|
||||||
//View Only
|
//View Only
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public string OriginalTitle { get; set; }
|
||||||
public List<AlternativeTitleResource> AlternateTitles { get; set; }
|
public List<AlternativeTitleResource> AlternateTitles { get; set; }
|
||||||
public int? SecondaryYear { get; set; }
|
public int? SecondaryYear { get; set; }
|
||||||
public int SecondaryYearSourceId { get; set; }
|
public int SecondaryYearSourceId { get; set; }
|
||||||
@ -86,10 +90,10 @@ public static MovieResource ToResource(this Movie model)
|
|||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
TmdbId = model.TmdbId,
|
TmdbId = model.TmdbId,
|
||||||
Title = model.Title,
|
Title = model.Title,
|
||||||
|
OriginalTitle = model.Title,
|
||||||
SortTitle = model.SortTitle,
|
SortTitle = model.SortTitle,
|
||||||
InCinemas = model.InCinemas,
|
InCinemas = model.InCinemas,
|
||||||
PhysicalRelease = model.PhysicalRelease,
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
PhysicalReleaseNote = model.PhysicalReleaseNote,
|
|
||||||
HasFile = model.HasFile,
|
HasFile = model.HasFile,
|
||||||
|
|
||||||
SizeOnDisk = size,
|
SizeOnDisk = size,
|
||||||
@ -100,7 +104,6 @@ public static MovieResource ToResource(this Movie model)
|
|||||||
|
|
||||||
Year = model.Year,
|
Year = model.Year,
|
||||||
SecondaryYear = model.SecondaryYear,
|
SecondaryYear = model.SecondaryYear,
|
||||||
SecondaryYearSourceId = model.SecondaryYearSourceId,
|
|
||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
QualityProfileId = model.ProfileId,
|
QualityProfileId = model.ProfileId,
|
||||||
@ -131,7 +134,69 @@ public static MovieResource ToResource(this Movie model)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MovieResource ToResource(this Movie model, IUpgradableSpecification upgradableSpecification)
|
public static MovieResource ToResource(this Movie model, MovieTranslation movieTranslation)
|
||||||
|
{
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
long size = model.MovieFile?.Size ?? 0;
|
||||||
|
MovieFileResource movieFile = model.MovieFile?.ToResource(model);
|
||||||
|
|
||||||
|
var translatedTitle = movieTranslation?.Title ?? model.Title;
|
||||||
|
var translatedOverview = movieTranslation?.Overview ?? model.Overview;
|
||||||
|
|
||||||
|
return new MovieResource
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
TmdbId = model.TmdbId,
|
||||||
|
Title = translatedTitle,
|
||||||
|
OriginalTitle = model.Title,
|
||||||
|
SortTitle = translatedTitle.NormalizeTitle(),
|
||||||
|
InCinemas = model.InCinemas,
|
||||||
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
|
HasFile = model.HasFile,
|
||||||
|
|
||||||
|
SizeOnDisk = size,
|
||||||
|
Status = model.Status,
|
||||||
|
Overview = translatedOverview,
|
||||||
|
|
||||||
|
Images = model.Images,
|
||||||
|
|
||||||
|
Year = model.Year,
|
||||||
|
SecondaryYear = model.SecondaryYear,
|
||||||
|
|
||||||
|
Path = model.Path,
|
||||||
|
QualityProfileId = model.ProfileId,
|
||||||
|
|
||||||
|
Monitored = model.Monitored,
|
||||||
|
MinimumAvailability = model.MinimumAvailability,
|
||||||
|
|
||||||
|
IsAvailable = model.IsAvailable(),
|
||||||
|
FolderName = model.FolderName(),
|
||||||
|
|
||||||
|
Runtime = model.Runtime,
|
||||||
|
CleanTitle = model.CleanTitle,
|
||||||
|
ImdbId = model.ImdbId,
|
||||||
|
TitleSlug = model.TitleSlug,
|
||||||
|
RootFolderPath = model.RootFolderPath,
|
||||||
|
Certification = model.Certification,
|
||||||
|
Website = model.Website,
|
||||||
|
Genres = model.Genres,
|
||||||
|
Tags = model.Tags,
|
||||||
|
Added = model.Added,
|
||||||
|
AddOptions = model.AddOptions,
|
||||||
|
AlternateTitles = model.AlternativeTitles.ToResource(),
|
||||||
|
Ratings = model.Ratings,
|
||||||
|
MovieFile = movieFile,
|
||||||
|
YouTubeTrailerId = model.YouTubeTrailerId,
|
||||||
|
Studio = model.Studio,
|
||||||
|
Collection = model.Collection
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MovieResource ToResource(this Movie model, IUpgradableSpecification upgradableSpecification, MovieTranslation movieTranslation)
|
||||||
{
|
{
|
||||||
if (model == null)
|
if (model == null)
|
||||||
{
|
{
|
||||||
@ -141,26 +206,27 @@ public static MovieResource ToResource(this Movie model, IUpgradableSpecificatio
|
|||||||
long size = model.MovieFile?.Size ?? 0;
|
long size = model.MovieFile?.Size ?? 0;
|
||||||
MovieFileResource movieFile = model.MovieFile?.ToResource(model, upgradableSpecification);
|
MovieFileResource movieFile = model.MovieFile?.ToResource(model, upgradableSpecification);
|
||||||
|
|
||||||
|
var translatedTitle = movieTranslation?.Title ?? model.Title;
|
||||||
|
var translatedOverview = movieTranslation?.Overview ?? model.Overview;
|
||||||
|
|
||||||
return new MovieResource
|
return new MovieResource
|
||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
TmdbId = model.TmdbId,
|
TmdbId = model.TmdbId,
|
||||||
Title = model.Title,
|
Title = translatedTitle,
|
||||||
SortTitle = model.SortTitle,
|
SortTitle = translatedTitle.NormalizeTitle(),
|
||||||
InCinemas = model.InCinemas,
|
InCinemas = model.InCinemas,
|
||||||
PhysicalRelease = model.PhysicalRelease,
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
PhysicalReleaseNote = model.PhysicalReleaseNote,
|
|
||||||
HasFile = model.HasFile,
|
HasFile = model.HasFile,
|
||||||
|
|
||||||
SizeOnDisk = size,
|
SizeOnDisk = size,
|
||||||
Status = model.Status,
|
Status = model.Status,
|
||||||
Overview = model.Overview,
|
Overview = translatedOverview,
|
||||||
|
|
||||||
Images = model.Images,
|
Images = model.Images,
|
||||||
|
|
||||||
Year = model.Year,
|
Year = model.Year,
|
||||||
SecondaryYear = model.SecondaryYear,
|
SecondaryYear = model.SecondaryYear,
|
||||||
SecondaryYearSourceId = model.SecondaryYearSourceId,
|
|
||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
QualityProfileId = model.ProfileId,
|
QualityProfileId = model.ProfileId,
|
||||||
@ -207,7 +273,6 @@ public static Movie ToModel(this MovieResource resource)
|
|||||||
SortTitle = resource.SortTitle,
|
SortTitle = resource.SortTitle,
|
||||||
InCinemas = resource.InCinemas,
|
InCinemas = resource.InCinemas,
|
||||||
PhysicalRelease = resource.PhysicalRelease,
|
PhysicalRelease = resource.PhysicalRelease,
|
||||||
PhysicalReleaseNote = resource.PhysicalReleaseNote,
|
|
||||||
|
|
||||||
Overview = resource.Overview,
|
Overview = resource.Overview,
|
||||||
|
|
||||||
@ -215,7 +280,6 @@ public static Movie ToModel(this MovieResource resource)
|
|||||||
|
|
||||||
Year = resource.Year,
|
Year = resource.Year,
|
||||||
SecondaryYear = resource.SecondaryYear,
|
SecondaryYear = resource.SecondaryYear,
|
||||||
SecondaryYearSourceId = resource.SecondaryYearSourceId,
|
|
||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.QualityProfileId,
|
ProfileId = resource.QualityProfileId,
|
||||||
@ -254,11 +318,6 @@ public static List<MovieResource> ToResource(this IEnumerable<Movie> movies)
|
|||||||
return movies.Select(ToResource).ToList();
|
return movies.Select(ToResource).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<MovieResource> ToResource(this IEnumerable<Movie> movies, IUpgradableSpecification upgradableSpecification)
|
|
||||||
{
|
|
||||||
return movies.ToList().ConvertAll(f => f.ToResource(upgradableSpecification));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Movie> ToModel(this IEnumerable<MovieResource> resources)
|
public static List<Movie> ToModel(this IEnumerable<MovieResource> resources)
|
||||||
{
|
{
|
||||||
return resources.Select(ToModel).ToList();
|
return resources.Select(ToModel).ToList();
|
||||||
|
Loading…
Reference in New Issue
Block a user