1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-09 15:01:39 -04:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Qstick
1b4a6b1309 New: Add Changes to UpdatedEvent Notifications 2022-06-04 00:02:09 -05:00
Qstick
fcebfe6759 Fixed: Duplicate changes in app updated modal
[common]
2022-06-04 00:01:56 -05:00
118 changed files with 690 additions and 1387 deletions

View File

@@ -173,6 +173,7 @@ stages:
key: 'yarn | "$(osName)" | yarn.lock'
restoreKeys: |
yarn | "$(osName)"
yarn
path: $(yarnCacheFolder)
displayName: Cache Yarn packages
- bash: ./build.sh --frontend
@@ -576,7 +577,6 @@ stages:
-e POSTGRES_PASSWORD=radarr \
-e POSTGRES_USER=radarr \
-p 5432:5432/tcp \
-v /usr/share/zoneinfo/America/Chicago:/etc/localtime:ro \
postgres:14
displayName: Start postgres
- bash: |
@@ -722,7 +722,6 @@ stages:
-e POSTGRES_PASSWORD=radarr \
-e POSTGRES_USER=radarr \
-p 5432:5432/tcp \
-v /usr/share/zoneinfo/America/Chicago:/etc/localtime:ro \
postgres:14
displayName: Start postgres
- bash: |
@@ -977,6 +976,7 @@ stages:
key: 'yarn | "$(osName)" | yarn.lock'
restoreKeys: |
yarn | "$(osName)"
yarn
path: $(yarnCacheFolder)
displayName: Cache Yarn packages
- bash: ./build.sh --lint

View File

@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import HeartRating from 'Components/HeartRating';
import Icon from 'Components/Icon';
import Label from 'Components/Label';
import Link from 'Components/Link/Link';
import TmdbRating from 'Components/TmdbRating';
import Tooltip from 'Components/Tooltip/Tooltip';
import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
import MovieDetailsLinks from 'Movie/Details/MovieDetailsLinks';
@@ -190,7 +190,7 @@ class AddNewMovieSearchResult extends Component {
<div>
<Label size={sizes.LARGE}>
<TmdbRating
<HeartRating
ratings={ratings}
iconSize={13}
/>

View File

@@ -1,5 +1,4 @@
.container {
display: flex;
.movie {
padding: 10px 20px;
width: 100%;
@@ -7,19 +6,3 @@
background-color: $menuItemHoverBackgroundColor;
}
}
.movie {
flex: 1 0 0;
overflow: hidden;
}
.tmdbLink {
composes: link from '~Components/Link/Link.css';
margin-left: auto;
color: $textColor;
}
.tmdbLinkIcon {
margin-left: 10px;
}

View File

@@ -1,8 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Icon from 'Components/Icon';
import Link from 'Components/Link/Link';
import { icons } from 'Helpers/Props';
import ImportMovieTitle from './ImportMovieTitle';
import styles from './ImportMovieSearchResult.css';
@@ -20,7 +18,6 @@ class ImportMovieSearchResult extends Component {
render() {
const {
tmdbId,
title,
year,
studio,
@@ -28,30 +25,17 @@ class ImportMovieSearchResult extends Component {
} = this.props;
return (
<div className={styles.container}>
<Link
className={styles.movie}
onPress={this.onPress}
>
<ImportMovieTitle
title={title}
year={year}
network={studio}
isExistingMovie={isExistingMovie}
/>
</Link>
<Link
className={styles.tmdbLink}
to={`https://www.themoviedb.org/movie/${tmdbId}`}
>
<Icon
className={styles.tmdbLinkIcon}
name={icons.EXTERNAL_LINK}
size={16}
/>
</Link>
</div>
<Link
className={styles.movie}
onPress={this.onPress}
>
<ImportMovieTitle
title={title}
year={year}
network={studio}
isExistingMovie={isExistingMovie}
/>
</Link>
);
}
}

View File

@@ -89,12 +89,12 @@ function AppUpdatedModalContent(props) {
<UpdateChanges
title={translate('New')}
changes={update.changes.new}
changes={Array.from(new Set(update.changes.new))}
/>
<UpdateChanges
title={translate('Fixed')}
changes={update.changes.fixed}
changes={Array.from(new Set(update.changes.fixed))}
/>
</div>
}

View File

@@ -1,9 +1,6 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import AvailabilitySelectInput from 'Components/Form/AvailabilitySelectInput';
import QualityProfileSelectInputConnector from 'Components/Form/QualityProfileSelectInputConnector';
import RootFolderSelectInputConnector from 'Components/Form/RootFolderSelectInputConnector';
import SelectInput from 'Components/Form/SelectInput';
import SpinnerButton from 'Components/Link/SpinnerButton';
import PageContentFooter from 'Components/Page/PageContentFooter';
@@ -25,9 +22,6 @@ class CollectionFooter extends Component {
this.state = {
monitor: NO_CHANGE,
monitored: NO_CHANGE,
qualityProfileId: NO_CHANGE,
minimumAvailability: NO_CHANGE,
rootFolderPath: NO_CHANGE,
destinationRootFolder: null
};
}
@@ -42,10 +36,7 @@ class CollectionFooter extends Component {
if (prevProps.isSaving && !isSaving && !saveError) {
this.setState({
monitored: NO_CHANGE,
monitor: NO_CHANGE,
qualityProfileId: NO_CHANGE,
rootFolderPath: NO_CHANGE,
minimumAvailability: NO_CHANGE
monitor: NO_CHANGE
});
}
@@ -64,10 +55,7 @@ class CollectionFooter extends Component {
onUpdateSelectedPress = () => {
const {
monitor,
monitored,
qualityProfileId,
minimumAvailability,
rootFolderPath
monitored
} = this.state;
const changes = {};
@@ -80,18 +68,6 @@ class CollectionFooter extends Component {
changes.monitor = monitor;
}
if (qualityProfileId !== NO_CHANGE) {
changes.qualityProfileId = qualityProfileId;
}
if (minimumAvailability !== NO_CHANGE) {
changes.minimumAvailability = minimumAvailability;
}
if (rootFolderPath !== NO_CHANGE) {
changes.rootFolderPath = rootFolderPath;
}
this.props.onUpdateSelectedPress(changes);
};
@@ -106,10 +82,7 @@ class CollectionFooter extends Component {
const {
monitored,
monitor,
qualityProfileId,
minimumAvailability,
rootFolderPath
monitor
} = this.state;
const monitoredOptions = [
@@ -152,52 +125,6 @@ class CollectionFooter extends Component {
/>
</div>
<div className={styles.inputContainer}>
<CollectionFooterLabel
label={translate('QualityProfile')}
isSaving={isSaving && qualityProfileId !== NO_CHANGE}
/>
<QualityProfileSelectInputConnector
name="qualityProfileId"
value={qualityProfileId}
includeNoChange={true}
isDisabled={!selectedCount}
onChange={this.onInputChange}
/>
</div>
<div className={styles.inputContainer}>
<CollectionFooterLabel
label={translate('MinimumAvailability')}
isSaving={isSaving && minimumAvailability !== NO_CHANGE}
/>
<AvailabilitySelectInput
name="minimumAvailability"
value={minimumAvailability}
includeNoChange={true}
isDisabled={!selectedCount}
onChange={this.onInputChange}
/>
</div>
<div className={styles.inputContainer}>
<CollectionFooterLabel
label={translate('RootFolder')}
isSaving={isSaving && rootFolderPath !== NO_CHANGE}
/>
<RootFolderSelectInputConnector
name="rootFolderPath"
value={rootFolderPath}
includeNoChange={true}
isDisabled={!selectedCount}
selectedValueOptions={{ includeFreeSpace: false }}
onChange={this.onInputChange}
/>
</div>
<div className={styles.buttonContainer}>
<div className={styles.buttonContainerContent}>
<CollectionFooterLabel

View File

@@ -0,0 +1,5 @@
.image {
align-content: center;
margin-right: 5px;
vertical-align: -0.125em;
}

File diff suppressed because one or more lines are too long

View File

@@ -22,11 +22,11 @@ class ImdbRating extends PureComponent {
let ratingString = '0.0';
if (rating) {
ratingString = `${rating.value.toFixed(1)}`;
ratingString = `${rating.value}`;
}
return (
<span title={`${rating ? rating.votes : 0} votes`}>
<span title={`${rating.votes} votes`}>
{
!hideIcon &&
<img

View File

@@ -21,11 +21,9 @@ class RottenTomatoRating extends PureComponent {
const rating = ratings.rottenTomatoes;
let ratingString = '0%';
let ratingImage = rtFresh;
if (rating) {
ratingString = `${rating.value}%`;
ratingImage = rating.value > 50 ? rtFresh : rtRotten;
}
return (
@@ -34,7 +32,7 @@ class RottenTomatoRating extends PureComponent {
!hideIcon &&
<img
className={styles.image}
src={ratingImage}
src={rating.value > 50 ? rtFresh : rtRotten}
style={{
height: `${iconSize}px`
}}

View File

@@ -22,7 +22,7 @@ class TmdbRating extends PureComponent {
let ratingString = '0%';
if (rating) {
ratingString = `${(rating.value * 10).toFixed()}%`;
ratingString = `${rating.value * 10}%`;
}
return (

View File

@@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
import TmdbRating from 'Components/TmdbRating';
import HeartRating from 'Components/HeartRating';
import { getMovieStatusDetails } from 'Movie/MovieStatus';
import formatRuntime from 'Utilities/Date/formatRuntime';
import getRelativeDate from 'Utilities/Date/getRelativeDate';
@@ -111,7 +111,7 @@ function DiscoverMoviePosterInfo(props) {
if (sortKey === 'ratings' && ratings) {
return (
<div className={styles.info}>
<TmdbRating
<HeartRating
ratings={ratings}
/>
</div>

View File

@@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import HeartRating from 'Components/HeartRating';
import Icon from 'Components/Icon';
import ImportListListConnector from 'Components/ImportListListConnector';
import IconButton from 'Components/Link/IconButton';
@@ -7,7 +8,6 @@ import Link from 'Components/Link/Link';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
import TmdbRating from 'Components/TmdbRating';
import Popover from 'Components/Tooltip/Popover';
import AddNewDiscoverMovieModal from 'DiscoverMovie/AddNewDiscoverMovieModal';
import ExcludeMovieModal from 'DiscoverMovie/Exclusion/ExcludeMovieModal';
@@ -245,7 +245,7 @@ class DiscoverMovieRow extends Component {
key={name}
className={styles[name]}
>
<TmdbRating
<HeartRating
ratings={ratings}
/>
</VirtualTableRowCell>

View File

@@ -102,21 +102,12 @@ function MovieIndexSortMenu(props) {
</SortMenuItem>
<SortMenuItem
name="imdbRating"
name="ratings"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('ImdbRating')}
</SortMenuItem>
<SortMenuItem
name="tmdbRating"
sortKey={sortKey}
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('TmdbRating')}
{translate('Ratings')}
</SortMenuItem>
<SortMenuItem

View File

@@ -77,9 +77,7 @@
flex: 0 0 120px;
}
.imdbRating,
.tmdbRating,
.rottenTomatoesRating {
.ratings {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 80px;

View File

@@ -84,9 +84,7 @@
flex: 0 0 120px;
}
.imdbRating,
.tmdbRating,
.rottenTomatoesRating {
.ratings {
composes: cell;
flex: 0 0 80px;

View File

@@ -1,15 +1,13 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import HeartRating from 'Components/HeartRating';
import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import RottenTomatoRating from 'Components/RottenTomatoRating';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
import TagListConnector from 'Components/TagListConnector';
import TmdbRating from 'Components/TmdbRating';
import Tooltip from 'Components/Tooltip/Tooltip';
import { icons, kinds } from 'Helpers/Props';
import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal';
@@ -351,39 +349,13 @@ class MovieIndexRow extends Component {
);
}
if (name === 'tmdbRating') {
if (name === 'ratings') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
<TmdbRating
ratings={ratings}
/>
</VirtualTableRowCell>
);
}
if (name === 'rottenTomatoesRating') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
<RottenTomatoRating
ratings={ratings}
/>
</VirtualTableRowCell>
);
}
if (name === 'imdbRating') {
return (
<VirtualTableRowCell
key={name}
className={styles[name]}
>
<ImdbRating
<HeartRating
ratings={ratings}
/>
</VirtualTableRowCell>

View File

@@ -561,7 +561,7 @@ export const actionHandlers = handleThunks({
}, []);
const promise = createAjaxRequest({
url: '/importlist/movie',
url: '/movie/import',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify(allNewMovies)

View File

@@ -162,14 +162,6 @@ export const filterPredicates = {
return predicate(rating, filterValue);
},
rottenTomatoesRating: function(item, filterValue, type) {
const predicate = filterTypePredicates[type];
const rating = item.ratings.rottenTomatoes ? item.ratings.rottenTomatoes.value : 0;
return predicate(rating, filterValue);
},
imdbVotes: function(item, filterValue, type) {
const predicate = filterTypePredicates[type];

View File

@@ -1,12 +1,10 @@
import _ from 'lodash';
import { createAction } from 'redux-actions';
import { batchActions } from 'redux-batched-actions';
import { filterBuilderTypes, filterBuilderValueTypes, filterTypePredicates, sortDirections } from 'Helpers/Props';
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
import { createThunk, handleThunks } from 'Store/thunks';
import sortByName from 'Utilities/Array/sortByName';
import createAjaxRequest from 'Utilities/createAjaxRequest';
import getNewMovie from 'Utilities/Movie/getNewMovie';
import translate from 'Utilities/String/translate';
import { set, update, updateItem } from './baseActions';
import createHandleActions from './Creators/createHandleActions';
import createSaveProviderHandler from './Creators/createSaveProviderHandler';
@@ -65,81 +63,19 @@ export const defaultState = {
}
],
filterPredicates: {
genres: function(item, filterValue, type) {
const predicate = filterTypePredicates[type];
let allGenres = [];
item.movies.forEach((movie) => {
allGenres = allGenres.concat(movie.genres);
});
const genres = Array.from(new Set(allGenres)).slice(0, 3);
return predicate(genres, filterValue);
},
totalMovies: function(item, filterValue, type) {
const predicate = filterTypePredicates[type];
const { movies } = item;
const totalMovies = movies.length;
return predicate(totalMovies, filterValue);
}
},
filterPredicates: {},
filterBuilderProps: [
{
name: 'title',
label: translate('Title'),
label: 'Title',
type: filterBuilderTypes.STRING
},
{
name: 'monitored',
label: translate('Monitored'),
label: 'Monitored',
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.BOOL
},
{
name: 'qualityProfileId',
label: translate('QualityProfile'),
type: filterBuilderTypes.EXACT,
valueType: filterBuilderValueTypes.QUALITY_PROFILE
},
{
name: 'rootFolderPath',
label: translate('RootFolder'),
type: filterBuilderTypes.STRING
},
{
name: 'genres',
label: translate('Genres'),
type: filterBuilderTypes.ARRAY,
optionsSelector: function(items) {
const genreList = items.reduce((acc, collection) => {
let collectionGenres = [];
collection.movies.forEach((movie) => {
collectionGenres = collectionGenres.concat(movie.genres);
});
const genres = Array.from(new Set(collectionGenres)).slice(0, 3);
genres.forEach((genre) => {
acc.push({
id: genre,
name: genre
});
});
return acc;
}, []);
return genreList.sort(sortByName);
}
},
{
name: 'totalMovies',
label: translate('TotalMovies'),
type: filterBuilderTypes.NUMBER
}
]
};
@@ -318,32 +254,27 @@ export const actionHandlers = handleThunks({
const {
collectionIds,
monitored,
monitor,
qualityProfileId,
rootFolderPath,
minimumAvailability
monitor
} = payload;
const response = {};
const collections = [];
if (payload.hasOwnProperty('monitored')) {
response.monitored = monitored;
}
collectionIds.forEach((id) => {
const collectionToUpdate = { id };
if (payload.hasOwnProperty('monitored')) {
collectionToUpdate.monitored = monitored;
}
collections.push(collectionToUpdate);
});
if (payload.hasOwnProperty('monitor')) {
response.monitorMovies = monitor === 'monitored';
}
if (payload.hasOwnProperty('qualityProfileId')) {
response.qualityProfileId = qualityProfileId;
}
if (payload.hasOwnProperty('minimumAvailability')) {
response.minimumAvailability = minimumAvailability;
}
response.rootFolderPath = rootFolderPath;
response.collectionIds = collectionIds;
response.collections = collections;
dispatch(set({
section,

View File

@@ -178,20 +178,8 @@ export const defaultState = {
isVisible: true
},
{
name: 'tmdbRating',
label: translate('TmdbRating'),
isSortable: true,
isVisible: false
},
{
name: 'rottenTomatoesRating',
label: translate('RottenTomatoesRating'),
isSortable: true,
isVisible: false
},
{
name: 'imdbRating',
label: translate('ImdbRating'),
name: 'ratings',
label: translate('Ratings'),
isSortable: true,
isVisible: false
},
@@ -236,22 +224,10 @@ export const defaultState = {
return originalLanguage.name;
},
imdbRating: function(item) {
ratings: function(item) {
const { ratings = {} } = item;
return ratings.imdb ? ratings.imdb.value : 0;
},
tmdbRating: function(item) {
const { ratings = {} } = item;
return ratings.tmdb ? ratings.tmdb.value : 0;
},
rottenTomatoesRating: function(item) {
const { ratings = {} } = item;
return ratings.rottenTomatoes ? ratings.rottenTomatoes.value : 0;
return ratings.tmdb? ratings.tmdb.value : 0;
}
},
@@ -437,11 +413,6 @@ export const defaultState = {
label: translate('ImdbRating'),
type: filterBuilderTypes.NUMBER
},
{
name: 'rottenTomatoesRating',
label: translate('RottenTomatoesRating'),
type: filterBuilderTypes.NUMBER
},
{
name: 'imdbVotes',
label: translate('ImdbVotes'),

View File

@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using NLog;
using NLog.Fluent;
@@ -10,46 +8,47 @@ namespace NzbDrone.Common.Instrumentation.Extensions
{
public static readonly Logger SentryLogger = LogManager.GetLogger("Sentry");
public static LogEventBuilder SentryFingerprint(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder SentryFingerprint(this LogBuilder logBuilder, params string[] fingerprint)
{
return logBuilder.Property("Sentry", fingerprint);
}
public static LogEventBuilder WriteSentryDebug(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryDebug(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Debug, fingerprint);
}
public static LogEventBuilder WriteSentryInfo(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryInfo(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Info, fingerprint);
}
public static LogEventBuilder WriteSentryWarn(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryWarn(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Warn, fingerprint);
}
public static LogEventBuilder WriteSentryError(this LogEventBuilder logBuilder, params string[] fingerprint)
public static LogBuilder WriteSentryError(this LogBuilder logBuilder, params string[] fingerprint)
{
return LogSentryMessage(logBuilder, LogLevel.Error, fingerprint);
}
private static LogEventBuilder LogSentryMessage(LogEventBuilder logBuilder, LogLevel level, string[] fingerprint)
private static LogBuilder LogSentryMessage(LogBuilder logBuilder, LogLevel level, string[] fingerprint)
{
SentryLogger.ForLogEvent(level)
.CopyLogEvent(logBuilder.LogEvent)
SentryLogger.Log(level)
.CopyLogEvent(logBuilder.LogEventInfo)
.SentryFingerprint(fingerprint)
.Log();
.Write();
return logBuilder.Property<string>("Sentry", null);
return logBuilder.Property("Sentry", null);
}
private static LogEventBuilder CopyLogEvent(this LogEventBuilder logBuilder, LogEventInfo logEvent)
private static LogBuilder CopyLogEvent(this LogBuilder logBuilder, LogEventInfo logEvent)
{
return logBuilder.TimeStamp(logEvent.TimeStamp)
return logBuilder.LoggerName(logEvent.LoggerName)
.TimeStamp(logEvent.TimeStamp)
.Message(logEvent.Message, logEvent.Parameters)
.Properties(logEvent.Properties.Select(p => new KeyValuePair<string, object>(p.Key.ToString(), p.Value)))
.Properties(logEvent.Properties.ToDictionary(v => v.Key, v => v.Value))
.Exception(logEvent.Exception);
}
}

View File

@@ -1,16 +1,13 @@
using System;
using System.Text;
using NLog;
using NLog;
using NLog.Targets;
namespace NzbDrone.Common.Instrumentation
{
public class NzbDroneFileTarget : FileTarget
{
protected override void RenderFormattedMessage(LogEventInfo logEvent, StringBuilder target)
protected override string GetFormattedMessage(LogEventInfo logEvent)
{
var result = CleanseLogMessage.Cleanse(Layout.Render(logEvent));
target.Append(result);
return CleanseLogMessage.Cleanse(Layout.Render(logEvent));
}
}
}

View File

@@ -34,8 +34,6 @@ namespace NzbDrone.Common.Instrumentation
var appFolderInfo = new AppFolderInfo(startupContext);
RegisterGlobalFilters();
if (Debugger.IsAttached)
{
RegisterDebugger();
@@ -99,21 +97,10 @@ namespace NzbDrone.Common.Instrumentation
target.Layout = "[${level}] [${threadid}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}${exception:format=Data}${newline}}";
var loggingRule = new LoggingRule("*", LogLevel.Trace, target);
LogManager.Configuration.AddTarget("debugger", target);
LogManager.Configuration.LoggingRules.Add(loggingRule);
}
private static void RegisterGlobalFilters()
{
LogManager.Setup().LoadConfiguration(c =>
{
c.ForLogger("Microsoft.Hosting.Lifetime*").WriteToNil(LogLevel.Info);
c.ForLogger("System*").WriteToNil(LogLevel.Warn);
c.ForLogger("Microsoft*").WriteToNil(LogLevel.Warn);
});
}
private static void RegisterConsole()
{
var level = LogLevel.Trace;

View File

@@ -8,10 +8,10 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="NLog" Version="4.7.14" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.4" />
<PackageReference Include="Sentry" Version="3.15.0" />
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageReference Include="NLog.Targets.Syslog" Version="6.0.3" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />

View File

@@ -56,51 +56,6 @@ namespace NzbDrone.Core.Test.Datastore.Migration
movies.First().CollectionTmdbId.Should().Be(collections.First().TmdbId);
}
[Test]
public void should_skip_collection_from_movie_without_name()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
MinimumAvailability = 4,
ProfileId = 1,
MovieFileId = 0,
MovieMetadataId = 1,
Path = string.Format("/Movies/{0}", "Title"),
});
c.Insert.IntoTable("MovieMetadata").Row(new
{
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalTitle = "Title",
CleanOriginalTitle = "CleanTitle",
OriginalLanguage = 1,
TmdbId = 132456,
Collection = new { TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
});
var collections = db.Query<Collection208>("SELECT \"Id\", \"Title\", \"TmdbId\", \"Monitored\" FROM \"Collections\"");
collections.Should().HaveCount(1);
collections.First().TmdbId.Should().Be(11);
collections.First().Title.Should().Be("Collection 11");
collections.First().Monitored.Should().BeFalse();
var movies = db.Query<Movie208>("SELECT \"Id\", \"CollectionTmdbId\" FROM \"MovieMetadata\"");
movies.Should().HaveCount(1);
movies.First().CollectionTmdbId.Should().Be(collections.First().TmdbId);
}
[Test]
public void should_not_duplicate_collection()
{

View File

@@ -176,7 +176,7 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
public void should_return_ok_on_movie_imported_event()
{
GivenFolderExists(_downloadRootPath);
var importEvent = new MovieFileImportedEvent(new LocalMovie(), new MovieFile(), new List<MovieFile>(), true, new DownloadClientItem());
var importEvent = new MovieImportedEvent(new LocalMovie(), new MovieFile(), new List<MovieFile>(), true, new DownloadClientItem());
Subject.Check(importEvent).ShouldBeOk();
}

View File

@@ -91,7 +91,7 @@ namespace NzbDrone.Core.Test.HistoryTests
DownloadId = "abcd"
};
Subject.Handle(new MovieFileImportedEvent(localMovie, movieFile, new List<MovieFile>(), true, downloadClientItem));
Subject.Handle(new MovieImportedEvent(localMovie, movieFile, new List<MovieFile>(), true, downloadClientItem));
Mocker.GetMock<IHistoryRepository>()
.Verify(v => v.Insert(It.Is<MovieHistory>(h => h.SourceTitle == Path.GetFileNameWithoutExtension(localMovie.Path))));

View File

@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
}
[Test]
public void should_delete_orphaned_collection_with_meta_but_no_movie_items()
public void should_not_delete_unorphaned_collection_items()
{
var collection = Builder<MovieCollection>.CreateNew()
.With(h => h.Id = 3)
@@ -40,27 +40,6 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
Db.Insert(movie);
Subject.Clean();
AllStoredModels.Should().HaveCount(0);
}
[Test]
public void should_not_delete_unorphaned_collection()
{
var collection = Builder<MovieCollection>.CreateNew()
.With(h => h.Id = 3)
.With(h => h.TmdbId = 123456)
.With(h => h.Title = "Some Credit")
.BuildNew();
Db.Insert(collection);
var movieMeta = Builder<MovieMetadata>.CreateNew().With(m => m.CollectionTmdbId = collection.TmdbId).BuildNew();
Db.Insert(movieMeta);
var movie = Builder<Movie>.CreateNew().With(m => m.MovieMetadataId = movieMeta.Id).BuildNew();
Db.Insert(movie);
Subject.Clean();
AllStoredModels.Should().HaveCount(1);
}

View File

@@ -144,7 +144,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MovieImport
Subject.Import(new List<ImportDecision> { _approvedDecisions.First() }, true);
Mocker.GetMock<IEventAggregator>()
.Verify(v => v.PublishEvent(It.IsAny<MovieFileImportedEvent>()), Times.Once());
.Verify(v => v.PublishEvent(It.IsAny<MovieImportedEvent>()), Times.Once());
}
[Test]

View File

@@ -11,7 +11,6 @@ using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Collections;
using NzbDrone.Core.Movies.Commands;
using NzbDrone.Core.Movies.Credits;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
@@ -53,10 +52,6 @@ namespace NzbDrone.Core.Test.MovieTests
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(It.IsAny<int>()))
.Callback<int>((i) => { throw new MovieNotFoundException(i); });
Mocker.GetMock<IRootFolderService>()
.Setup(s => s.GetBestRootFolderPath(It.IsAny<string>()))
.Returns(string.Empty);
}
private void GivenNewMovieInfo(MovieMetadata movie)

View File

@@ -67,35 +67,6 @@ namespace NzbDrone.Core.Test.ParserTests
Parser.Parser.ParseMovieTitle(postTitle).PrimaryMovieTitle.Should().Be(title);
}
[TestCase("[MTBB] Kimi no Na wa. (2016) v2 [97681524].mkv", "Kimi no Na wa", "MTBB", 2016)]
[TestCase("[sam] Toward the Terra (1980) [BD 1080p TrueHD].mkv", "Toward the Terra", "sam", 1980)]
public void should_parse_anime_movie_title(string postTitle, string title, string releaseGroup, int year)
{
ParsedMovieInfo movie = Parser.Parser.ParseMovieTitle(postTitle);
using (new AssertionScope())
{
movie.PrimaryMovieTitle.Should().Be(title);
movie.ReleaseGroup.Should().Be(releaseGroup);
movie.Year.Should().Be(year);
}
}
[TestCase("[Arid] Cowboy Bebop - Knockin' on Heaven's Door v2 [00F4CDA0].mkv", "Cowboy Bebop - Knockin' on Heaven's Door", "Arid")]
[TestCase("[Baws] Evangelion 1.11 - You Are (Not) Alone v2 (1080p BD HEVC FLAC) [BF42B1C8].mkv", "Evangelion 1 11 - You Are (Not) Alone", "Baws")]
[TestCase("[Arid] 5 Centimeters per Second (BDRip 1920x1080 Hi10 FLAC) [FD8B6FF2].mkv", "5 Centimeters per Second", "Arid")]
[TestCase("[Baws] Evangelion 2.22 - You Can (Not) Advance (1080p BD HEVC FLAC) [56E7A5B8].mkv", "Evangelion 2 22 - You Can (Not) Advance", "Baws")]
[TestCase("[sam] Goblin Slayer - Goblin's Crown [BD 1080p FLAC] [CD298D48].mkv", "Goblin Slayer - Goblin's Crown", "sam")]
[TestCase("[Kulot] Violet Evergarden Gaiden Eien to Jidou Shuki Ningyou [Dual-Audio][BDRip 1920x804 HEVC FLACx2] [91FC62A8].mkv", "Violet Evergarden Gaiden Eien to Jidou Shuki Ningyou", "Kulot")]
public void should_parse_anime_movie_title_without_year(string postTitle, string title, string releaseGroup)
{
ParsedMovieInfo movie = Parser.Parser.ParseMovieTitle(postTitle);
using (new AssertionScope())
{
movie.PrimaryMovieTitle.Should().Be(title);
movie.ReleaseGroup.Should().Be(releaseGroup);
}
}
[TestCase("Movie.Aufbruch.nach.Pandora.Extended.2009.German.DTS.720p.BluRay.x264-SoW", "Movie Aufbruch nach Pandora", "Extended", 2009)]
[TestCase("Drop.Movie.1994.German.AC3D.DL.720p.BluRay.x264-KLASSiGERHD", "Drop Movie", "", 1994)]
[TestCase("Kick.Movie.2.2013.German.DTS.DL.720p.BluRay.x264-Pate", "Kick Movie 2", "", 2013)]

View File

@@ -41,14 +41,6 @@ namespace NzbDrone.Core.Test.ParserTests
ParseAndVerifyQuality(title, Source.TELESYNC, proper, Resolution.R720p);
}
[TestCase("Movie Name 2018 NEW PROPER 720p HD-CAM X264 HQ-CPG", true)]
[TestCase("Movie Name (2022) 1080p HQCAM ENG x264 AAC - QRips", false)]
[TestCase("Movie Name (2018) 720p Hindi HQ CAMrip x264 AAC 1.4GB", false)]
public void should_parse_cam(string title, bool proper)
{
ParseAndVerifyQuality(title, Source.CAM, proper, Resolution.Unknown);
}
[TestCase("S07E23 .avi ", false)]
[TestCase("Movie Name S02E01 HDTV XviD 2HD", false)]
[TestCase("Movie Name S05E11 PROPER HDTV XviD 2HD", true)]
@@ -197,7 +189,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie.Title.2020.MULTi.1080p.WEB.H264-ALLDAYiN (S:285/L:11)", false)]
[TestCase("Movie Title (2020) MULTi WEB 1080p x264-JiHEFF (S:317/L:28)", false)]
[TestCase("Movie.Titles.2020.1080p.NF.WEB.DD2.0.x264-SNEAkY", false)]
[TestCase("The.Movie.2022.NORDiC.1080p.DV.HDR.WEB.H 265-NiDHUG", false)]
public void should_parse_webdl1080p_quality(string title, bool proper)
{
ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R1080p);
@@ -216,7 +207,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie.Name.2016.03.14.2160p.WEB.PROPER.h264-spamTV", true)]
[TestCase("[HorribleSubs] Movie Title! 2018 [Web][MKV][h264][2160p][AAC 2.0][Softsubs (HorribleSubs)]", false)]
[TestCase("Movie Name 2020 WEB-DL 4K H265 10bit HDR DDP5.1 Atmos-PTerWEB", false)]
[TestCase("The.Movie.2022.NORDiC.2160p.DV.HDR.WEB.H.265-NiDHUG", false)]
public void should_parse_webdl2160p_quality(string title, bool proper)
{
ParseAndVerifyQuality(title, Source.WEBDL, proper, Resolution.R2160p);

View File

@@ -1,5 +1,4 @@
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
@@ -19,8 +18,6 @@ namespace NzbDrone.Core.CustomFormats
return (ICustomFormatSpecification)MemberwiseClone();
}
public abstract NzbDroneValidationResult Validate();
public bool IsSatisfiedBy(ParsedMovieInfo movieInfo)
{
var match = IsSatisfiedByWithoutNegate(movieInfo);

View File

@@ -1,5 +1,4 @@
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
@@ -12,8 +11,6 @@ namespace NzbDrone.Core.CustomFormats
bool Negate { get; set; }
bool Required { get; set; }
NzbDroneValidationResult Validate();
ICustomFormatSpecification Clone();
bool IsSatisfiedBy(ParsedMovieInfo movieInfo);
}

View File

@@ -1,31 +1,11 @@
using System;
using System.Collections.Generic;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class IndexerFlagSpecificationValidator : AbstractValidator<IndexerFlagSpecification>
{
public IndexerFlagSpecificationValidator()
{
RuleFor(c => c.Value).NotEmpty();
RuleFor(c => c.Value).Custom((qualityValue, context) =>
{
if (!Enum.IsDefined(typeof(IndexerFlags), qualityValue))
{
context.AddFailure(string.Format("Invalid indexer flag condition value: {0}", qualityValue));
}
});
}
}
public class IndexerFlagSpecification : CustomFormatSpecificationBase
{
private static readonly IndexerFlagSpecificationValidator Validator = new IndexerFlagSpecificationValidator();
public override int Order => 4;
public override string ImplementationName => "Indexer Flag";
@@ -37,10 +17,5 @@ namespace NzbDrone.Core.CustomFormats
var flags = movieInfo?.ExtraInfo?.GetValueOrDefault("IndexerFlags") as IndexerFlags?;
return flags?.HasFlag((IndexerFlags)Value) == true;
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,31 +1,11 @@
using System.Linq;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class LanguageSpecificationValidator : AbstractValidator<LanguageSpecification>
{
public LanguageSpecificationValidator()
{
RuleFor(c => c.Value).NotEmpty();
RuleFor(c => c.Value).Custom((value, context) =>
{
if (!Language.All.Any(o => o.Id == value))
{
context.AddFailure(string.Format("Invalid Language condition value: {0}", value));
}
});
}
}
public class LanguageSpecification : CustomFormatSpecificationBase
{
private static readonly LanguageSpecificationValidator Validator = new LanguageSpecificationValidator();
public override int Order => 3;
public override string ImplementationName => "Language";
@@ -39,10 +19,5 @@ namespace NzbDrone.Core.CustomFormats
: (Language)Value;
return movieInfo?.Languages?.Contains(comparedLanguage) ?? false;
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,31 +1,11 @@
using System;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class QualityModifierSpecificationValidator : AbstractValidator<QualityModifierSpecification>
{
public QualityModifierSpecificationValidator()
{
RuleFor(c => c.Value).NotEmpty();
RuleFor(c => c.Value).Custom((qualityValue, context) =>
{
if (!Enum.IsDefined(typeof(Modifier), qualityValue))
{
context.AddFailure(string.Format("Invalid quality modifier condition value: {0}", qualityValue));
}
});
}
}
public class QualityModifierSpecification : CustomFormatSpecificationBase
{
private static readonly QualityModifierSpecificationValidator Validator = new QualityModifierSpecificationValidator();
public override int Order => 7;
public override string ImplementationName => "Quality Modifier";
@@ -36,10 +16,5 @@ namespace NzbDrone.Core.CustomFormats
{
return (movieInfo?.Quality?.Quality?.Modifier ?? (int)Modifier.NONE) == (Modifier)Value;
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,23 +1,10 @@
using System.Text.RegularExpressions;
using FluentValidation;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class RegexSpecificationBaseValidator : AbstractValidator<RegexSpecificationBase>
{
public RegexSpecificationBaseValidator()
{
RuleFor(c => c.Value).NotEmpty().WithMessage("Regex Pattern must not be empty");
}
}
public abstract class RegexSpecificationBase : CustomFormatSpecificationBase
{
private static readonly RegexSpecificationBaseValidator Validator = new RegexSpecificationBaseValidator();
protected Regex _regex;
protected string _raw;
@@ -28,11 +15,7 @@ namespace NzbDrone.Core.CustomFormats
set
{
_raw = value;
if (value.IsNotNullOrWhiteSpace())
{
_regex = new Regex(value, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
_regex = new Regex(value, RegexOptions.Compiled | RegexOptions.IgnoreCase);
}
}
@@ -45,10 +28,5 @@ namespace NzbDrone.Core.CustomFormats
return _regex.IsMatch(compared);
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,23 +1,11 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class ResolutionSpecificationValidator : AbstractValidator<ResolutionSpecification>
{
public ResolutionSpecificationValidator()
{
RuleFor(c => c.Value).NotEmpty();
}
}
public class ResolutionSpecification : CustomFormatSpecificationBase
{
private static readonly ResolutionSpecificationValidator Validator = new ResolutionSpecificationValidator();
public override int Order => 6;
public override string ImplementationName => "Resolution";
@@ -28,10 +16,5 @@ namespace NzbDrone.Core.CustomFormats
{
return (movieInfo?.Quality?.Quality?.Resolution ?? (int)Resolution.Unknown) == Value;
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,24 +1,11 @@
using System.Collections.Generic;
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class SizeSpecificationValidator : AbstractValidator<SizeSpecification>
{
public SizeSpecificationValidator()
{
RuleFor(c => c.Min).GreaterThan(0);
RuleFor(c => c.Max).GreaterThan(c => c.Min);
}
}
public class SizeSpecification : CustomFormatSpecificationBase
{
private static readonly SizeSpecificationValidator Validator = new SizeSpecificationValidator();
public override int Order => 8;
public override string ImplementationName => "Size";
@@ -34,10 +21,5 @@ namespace NzbDrone.Core.CustomFormats
return size > Min.Gigabytes() && size <= Max.Gigabytes();
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -1,23 +1,11 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.CustomFormats
{
public class SourceSpecificationValidator : AbstractValidator<SourceSpecification>
{
public SourceSpecificationValidator()
{
RuleFor(c => c.Value).NotEmpty();
}
}
public class SourceSpecification : CustomFormatSpecificationBase
{
private static readonly SourceSpecificationValidator Validator = new SourceSpecificationValidator();
public override int Order => 5;
public override string ImplementationName => "Source";
@@ -28,10 +16,5 @@ namespace NzbDrone.Core.CustomFormats
{
return (movieInfo?.Quality?.Quality?.Source ?? (int)Source.UNKNOWN) == (Source)Value;
}
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@@ -85,7 +85,7 @@ namespace NzbDrone.Core.Datastore.Migration
var moviePath = reader.GetString(3);
var data = STJson.Deserialize<MovieCollection207>(collection);
if (data.TmdbId == 0 || newCollections.Any(d => d.TmdbId == data.TmdbId))
if (newCollections.Any(d => d.TmdbId == data.TmdbId))
{
continue;
}
@@ -104,17 +104,15 @@ namespace NzbDrone.Core.Datastore.Migration
rootFolderPath = moviePath.GetParentPath();
}
var collectionName = data.Name ?? $"Collection {data.TmdbId}";
newCollections.Add(new MovieCollection208
{
TmdbId = data.TmdbId,
Title = collectionName,
CleanTitle = collectionName.CleanMovieTitle(),
SortTitle = Parser.Parser.NormalizeTitle(collectionName),
Title = data.Name,
CleanTitle = data.Name.CleanMovieTitle(),
SortTitle = Parser.Parser.NormalizeTitle(data.Name),
Added = added,
QualityProfileId = qualityProfileId,
RootFolderPath = rootFolderPath.TrimEnd('/', '\\', ' '),
RootFolderPath = rootFolderPath,
SearchOnAdd = true,
MinimumAvailability = minimumAvailability
});

View File

@@ -1,15 +0,0 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(211)]
public class more_movie_meta_index : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Index("IX_AlternativeTitles_MovieMetadataId").OnTable("AlternativeTitles").OnColumn("MovieMetadataId");
Create.Index("IX_Credits_MovieMetadataId").OnTable("Credits").OnColumn("MovieMetadataId");
}
}
}

View File

@@ -180,14 +180,14 @@ namespace NzbDrone.Core.Download
}
else
{
_logger.ForDebugEvent()
_logger.Debug()
.Message("No Movies were just imported, but all movies were previously imported, possible issue with download history.")
.Property("MovieId", trackedDownload.RemoteMovie.Movie.Id)
.Property("DownloadId", trackedDownload.DownloadItem.DownloadId)
.Property("Title", trackedDownload.DownloadItem.Title)
.Property("Path", trackedDownload.ImportItem.OutputPath.ToString())
.WriteSentryWarn("DownloadHistoryIncomplete")
.Log();
.Write();
}
trackedDownload.State = TrackedDownloadState.Imported;

View File

@@ -17,7 +17,7 @@ namespace NzbDrone.Core.Download.History
public class DownloadHistoryService : IDownloadHistoryService,
IHandle<MovieGrabbedEvent>,
IHandle<MovieFileImportedEvent>,
IHandle<MovieImportedEvent>,
IHandle<DownloadCompletedEvent>,
IHandle<DownloadFailedEvent>,
IHandle<DownloadIgnoredEvent>,
@@ -120,7 +120,7 @@ namespace NzbDrone.Core.Download.History
_repository.Insert(history);
}
public void Handle(MovieFileImportedEvent message)
public void Handle(MovieImportedEvent message)
{
if (!message.NewDownload)
{

View File

@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
public class DownloadMonitoringService : IExecute<RefreshMonitoredDownloadsCommand>,
IExecute<CheckForFinishedDownloadCommand>,
IHandle<MovieGrabbedEvent>,
IHandle<MovieFileImportedEvent>,
IHandle<MovieImportedEvent>,
IHandle<DownloadsProcessedEvent>,
IHandle<TrackedDownloadsRemovedEvent>
{
@@ -167,7 +167,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
_refreshDebounce.Execute();
}
public void Handle(MovieFileImportedEvent message)
public void Handle(MovieImportedEvent message)
{
_refreshDebounce.Execute();
}

View File

@@ -158,32 +158,22 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
{
var setRating = new XElement("ratings");
var defaultRatingSet = false;
if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0)
{
var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"), new XAttribute("default", "true"));
setRatethemoviedb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Tmdb.Votes));
setRating.Add(setRatethemoviedb);
}
if (movie.MovieMetadata.Value.Ratings.Imdb?.Votes > 0)
{
var setRateImdb = new XElement("rating", new XAttribute("name", "imdb"), new XAttribute("max", "10"), new XAttribute("default", "true"));
var setRateImdb = new XElement("rating", new XAttribute("name", "imdb"), new XAttribute("max", "10"));
setRateImdb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Imdb.Value));
setRateImdb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Imdb.Votes));
defaultRatingSet = true;
setRating.Add(setRateImdb);
}
if (movie.MovieMetadata.Value.Ratings.Tmdb?.Votes > 0)
{
var setRatethemoviedb = new XElement("rating", new XAttribute("name", "themoviedb"), new XAttribute("max", "10"));
setRatethemoviedb.Add(new XElement("value", movie.MovieMetadata.Value.Ratings.Tmdb.Value));
setRatethemoviedb.Add(new XElement("votes", movie.MovieMetadata.Value.Ratings.Tmdb.Votes));
if (!defaultRatingSet)
{
setRatethemoviedb.SetAttributeValue("default", "true");
}
setRating.Add(setRatethemoviedb);
}
details.Add(setRating);
}

View File

@@ -10,7 +10,7 @@ using NzbDrone.Core.ThingiProvider.Events;
namespace NzbDrone.Core.HealthCheck.Checks
{
[CheckOn(typeof(ProviderUpdatedEvent<IImportList>))]
[CheckOn(typeof(MovieFileImportedEvent), CheckOnCondition.FailedOnly)]
[CheckOn(typeof(MovieImportedEvent), CheckOnCondition.FailedOnly)]
[CheckOn(typeof(MovieImportFailedEvent), CheckOnCondition.SuccessfulOnly)]
public class ImportListRootFolderCheck : HealthCheckBase
{

View File

@@ -2,15 +2,13 @@ using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Localization;
using NzbDrone.Core.Movies.Collections;
using NzbDrone.Core.Movies.Events;
using NzbDrone.Core.RootFolders;
namespace NzbDrone.Core.HealthCheck.Checks
{
[CheckOn(typeof(ModelEvent<RootFolder>))]
[CheckOn(typeof(CollectionEditedEvent), CheckOnCondition.Always)]
public class MovieCollectionRootFolderCheck : HealthCheckBase
{
private readonly IMovieCollectionService _collectionService;

View File

@@ -20,7 +20,7 @@ namespace NzbDrone.Core.HealthCheck.Checks
[CheckOn(typeof(ProviderUpdatedEvent<IDownloadClient>))]
[CheckOn(typeof(ProviderDeletedEvent<IDownloadClient>))]
[CheckOn(typeof(ModelEvent<RemotePathMapping>))]
[CheckOn(typeof(MovieFileImportedEvent), CheckOnCondition.FailedOnly)]
[CheckOn(typeof(MovieImportedEvent), CheckOnCondition.FailedOnly)]
[CheckOn(typeof(MovieImportFailedEvent), CheckOnCondition.SuccessfulOnly)]
public class RemotePathMappingCheck : HealthCheckBase, IProvideHealthCheck
{

View File

@@ -77,15 +77,12 @@ namespace NzbDrone.Core.HealthCheck
.ToDictionary(g => g.Key, g => g.ToArray());
}
private void PerformHealthCheck(IProvideHealthCheck[] healthChecks, bool performServerChecks = false)
private void PerformHealthCheck(IProvideHealthCheck[] healthChecks)
{
var results = healthChecks.Select(c => c.Check())
.ToList();
if (performServerChecks)
{
results.AddRange(_serverSideNotificationService.GetServerChecks());
}
results.AddRange(_serverSideNotificationService.GetServerChecks());
foreach (var result in results)
{
@@ -111,17 +108,17 @@ namespace NzbDrone.Core.HealthCheck
{
if (message.Trigger == CommandTrigger.Manual)
{
PerformHealthCheck(_healthChecks, true);
PerformHealthCheck(_healthChecks);
}
else
{
PerformHealthCheck(_scheduledHealthChecks, true);
PerformHealthCheck(_scheduledHealthChecks);
}
}
public void HandleAsync(ApplicationStartedEvent message)
{
PerformHealthCheck(_startupHealthChecks, true);
PerformHealthCheck(_startupHealthChecks);
}
public void HandleAsync(IEvent message)

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Http;
@@ -24,37 +23,24 @@ namespace NzbDrone.Core.HealthCheck
private readonly IHttpRequestBuilderFactory _cloudRequestBuilder;
private readonly Logger _logger;
private readonly ICached<List<HealthCheck>> _cache;
public ServerSideNotificationService(IHttpClient client,
IConfigFileProvider configFileProvider,
IRadarrCloudRequestBuilder cloudRequestBuilder,
ICacheManager cacheManager,
Logger logger)
public ServerSideNotificationService(IHttpClient client, IConfigFileProvider configFileProvider, IRadarrCloudRequestBuilder cloudRequestBuilder, Logger logger)
{
_client = client;
_configFileProvider = configFileProvider;
_cloudRequestBuilder = cloudRequestBuilder.Services;
_logger = logger;
_cache = cacheManager.GetCache<List<HealthCheck>>(GetType());
}
public List<HealthCheck> GetServerChecks()
{
return _cache.Get("ServerChecks", () => RetrieveServerChecks(), TimeSpan.FromHours(2));
}
private List<HealthCheck> RetrieveServerChecks()
{
var request = _cloudRequestBuilder.Create()
.Resource("/notification")
.AddQueryParam("version", BuildInfo.Version)
.AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant())
.AddQueryParam("arch", RuntimeInformation.OSArchitecture)
.AddQueryParam("runtime", PlatformInfo.Platform.ToString().ToLowerInvariant())
.AddQueryParam("branch", _configFileProvider.Branch)
.Build();
.Resource("/notification")
.AddQueryParam("version", BuildInfo.Version)
.AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant())
.AddQueryParam("arch", RuntimeInformation.OSArchitecture)
.AddQueryParam("runtime", PlatformInfo.Platform.ToString().ToLowerInvariant())
.AddQueryParam("branch", _configFileProvider.Branch)
.Build();
try
{
_logger.Trace("Getting server side health notifications");

View File

@@ -27,13 +27,13 @@ namespace NzbDrone.Core.History
List<MovieHistory> FindByDownloadId(string downloadId);
List<MovieHistory> GetByMovieId(int movieId, MovieHistoryEventType? eventType);
void UpdateMany(List<MovieHistory> toUpdate);
string FindDownloadId(MovieFileImportedEvent trackedDownload);
string FindDownloadId(MovieImportedEvent trackedDownload);
List<MovieHistory> Since(DateTime date, MovieHistoryEventType? eventType);
}
public class HistoryService : IHistoryService,
IHandle<MovieGrabbedEvent>,
IHandle<MovieFileImportedEvent>,
IHandle<MovieImportedEvent>,
IHandle<DownloadFailedEvent>,
IHandle<MovieFileDeletedEvent>,
IHandle<MovieFileRenamedEvent>,
@@ -97,7 +97,7 @@ namespace NzbDrone.Core.History
_historyRepository.UpdateMany(toUpdate);
}
public string FindDownloadId(MovieFileImportedEvent trackedDownload)
public string FindDownloadId(MovieImportedEvent trackedDownload)
{
_logger.Debug("Trying to find downloadId for {0} from history", trackedDownload.ImportedMovie.Path);
@@ -170,7 +170,7 @@ namespace NzbDrone.Core.History
_historyRepository.Insert(history);
}
public void Handle(MovieFileImportedEvent message)
public void Handle(MovieImportedEvent message)
{
if (!message.NewDownload)
{

View File

@@ -16,10 +16,12 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
{
using (var mapper = _database.OpenConnection())
{
mapper.Execute(@"DELETE FROM ""Collections"" WHERE ""TmdbId"" IN (SELECT ""X"".""TmdbId"" FROM (SELECT ""Collections"".""TmdbId"", COUNT(""Movies"".""Id"") as ""MovieCount"" FROM ""Collections""
LEFT OUTER JOIN ""MovieMetadata"" ON ""Collections"".""TmdbId"" = ""MovieMetadata"".""CollectionTmdbId""
LEFT OUTER JOIN ""Movies"" ON ""Movies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
GROUP BY ""Collections"".""Id"") AS ""X"" WHERE ""X"".""MovieCount"" = 0)");
mapper.Execute(@"DELETE FROM ""Collections""
WHERE ""TmdbId"" IN (
SELECT ""Collections"".""TmdbId"" FROM ""Collections""
LEFT OUTER JOIN ""MovieMetadata""
ON ""Collections"".""TmdbId"" = ""MovieMetadata"".""CollectionTmdbId""
WHERE ""MovieMetadata"".""Id"" IS NULL)");
}
}
}

View File

@@ -23,7 +23,6 @@ namespace NzbDrone.Core.ImportLists
private readonly IImportListStatusService _importListStatusService;
private readonly IImportListMovieService _listMovieService;
private readonly ISearchForNewMovie _movieSearch;
private readonly IProvideMovieInfo _movieInfoService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly Logger _logger;
@@ -31,7 +30,6 @@ namespace NzbDrone.Core.ImportLists
IImportListStatusService importListStatusService,
IImportListMovieService listMovieService,
ISearchForNewMovie movieSearch,
IProvideMovieInfo movieInfoService,
IMovieMetadataService movieMetadataService,
Logger logger)
{
@@ -39,7 +37,6 @@ namespace NzbDrone.Core.ImportLists
_importListStatusService = importListStatusService;
_listMovieService = listMovieService;
_movieSearch = movieSearch;
_movieInfoService = movieInfoService;
_movieMetadataService = movieMetadataService;
_logger = logger;
}
@@ -87,10 +84,20 @@ namespace NzbDrone.Core.ImportLists
if (!importListReports.AnyFailure)
{
var alreadyMapped = result.Movies.Where(x => importListReports.Movies.Any(r => r.TmdbId == x.TmdbId));
var listMovies = MapMovieReports(importListReports.Movies.Where(x => !result.Movies.Any(r => r.TmdbId == x.TmdbId)).ToList()).Where(x => x.TmdbId > 0).ToList();
// TODO some opportunity to bulk map here if we had the tmdbIds
var listMovies = importListReports.Movies.Select(x =>
{
// Is it existing in result
var movie = result.Movies.FirstOrDefault(r => r.TmdbId == x.TmdbId);
if (movie != null)
{
movie.ListId = importList.Definition.Id;
}
return movie ?? MapMovieReport(x);
}).Where(x => x.TmdbId > 0).ToList();
listMovies.AddRange(alreadyMapped);
listMovies = listMovies.DistinctBy(x => x.TmdbId).ToList();
listMovies.ForEach(m => m.ListId = importList.Definition.Id);
@@ -141,10 +148,13 @@ namespace NzbDrone.Core.ImportLists
if (!importListReports.AnyFailure)
{
var listMovies = MapMovieReports(importListReports.Movies).Where(x => x.TmdbId > 0).ToList();
// TODO some opportunity to bulk map here if we had the tmdbIds
var listMovies = importListReports.Movies.Select(x =>
{
return MapMovieReport(x);
}).Where(x => x.TmdbId > 0).ToList();
listMovies = listMovies.DistinctBy(x => x.TmdbId).ToList();
listMovies.ForEach(m => m.ListId = importList.Definition.Id);
result.Movies.AddRange(listMovies);
_listMovieService.SyncMoviesForList(listMovies, importList.Definition.Id);
@@ -163,30 +173,21 @@ namespace NzbDrone.Core.ImportLists
return result;
}
private List<ImportListMovie> MapMovieReports(List<ImportListMovie> reports)
private ImportListMovie MapMovieReport(ImportListMovie report)
{
var mappedMovies = reports.Select(m => _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = m.Title, TmdbId = m.TmdbId, ImdbId = m.ImdbId, Year = m.Year }))
.Where(x => x != null)
.ToList();
var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year });
_movieMetadataService.UpsertMany(mappedMovies);
var mappedListMovie = new ImportListMovie { ListId = report.ListId };
var mappedListMovies = new List<ImportListMovie>();
foreach (var movieMeta in mappedMovies)
if (mappedMovie != null)
{
var mappedListMovie = new ImportListMovie();
_movieMetadataService.Upsert(mappedMovie);
if (movieMeta != null)
{
mappedListMovie.MovieMetadata = movieMeta;
mappedListMovie.MovieMetadataId = movieMeta.Id;
}
mappedListMovies.Add(mappedListMovie);
mappedListMovie.MovieMetadata = mappedMovie;
mappedListMovie.MovieMetadataId = mappedMovie.Id;
}
return mappedListMovies;
return mappedListMovie;
}
}
}

View File

@@ -90,7 +90,7 @@ namespace NzbDrone.Core.ImportLists.Trakt
[FieldDefinition(2, Label = "Certification", HelpText = "Filter movies by a certification (NR,G,PG,PG-13,R,NC-17), (Comma Separated)")]
public string Certification { get; set; }
[FieldDefinition(3, Label = "Genres", HelpText = "Filter movies by Trakt Genre Slug (Comma Separated) Only for Popular Lists")]
[FieldDefinition(3, Label = "Genres", HelpText = "Filter movies by Trakt Genre Slug (Comma Separated)")]
public string Genres { get; set; }
[FieldDefinition(4, Label = "Years", HelpText = "Filter movies by year or year range")]

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NLog.Config;
@@ -117,6 +117,7 @@ namespace NzbDrone.Core.Instrumentation
syslogTarget.MessageSend.Protocol = ProtocolType.Udp;
syslogTarget.MessageSend.Udp.Port = syslogPort;
syslogTarget.MessageSend.Udp.Server = syslogServer;
syslogTarget.MessageSend.Udp.ReconnectInterval = 500;
syslogTarget.MessageCreation.Rfc = RfcNumber.Rfc5424;
syslogTarget.MessageCreation.Rfc5424.AppName = _configFileProvider.InstanceName;

View File

@@ -59,7 +59,7 @@
"IndexerRssHealthCheckNoIndexers": "Da keine Indexer mit aktivierter RSS-Synchronisierung verfügbar sind, erfasst Radarr nicht automatisch neue Releases auf",
"IndexerSearchCheckNoAutomaticMessage": "Keine Indexer mit aktivierter automatischer Suche verfügbar. Radarr liefert keine automatischen Suchergebnisse",
"IndexerSearchCheckNoAvailableIndexersMessage": "Alle suchfähigen Indexer sind aufgrund der kürzlichen Indexerfehler vorübergehend nicht verfügbar",
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit aktivierter interaktiver Suche verfügbar, Radarr liefert keine interaktiven Suchergebnisse",
"IndexerSearchCheckNoInteractiveMessage": "Keine Indexer mit interaktiver Suche aktiviert, Radarr liefert keine interaktiven Suchergebnisse",
"IndexerStatusCheckAllClientMessage": "Alle Indexer sind aufgrund von Fehlern nicht verfügbar",
"IndexerStatusCheckSingleClientMessage": "Indexer aufgrund von Fehlern nicht verfügbar: {0}",
"Indexers": "Indexer",
@@ -256,7 +256,7 @@
"AlternativeTitle": "Alternative Titel",
"AllMoviesHiddenDueToFilter": "Alle Filme sind wegen dem Filter ausgeblendet.",
"Age": "Alter",
"AddNewMovie": "Neuen Film hinzufügen",
"AddNewMovie": "Neuer Film...",
"AddList": "Liste hinzufügen",
"SystemTimeCheckMessage": "Die Systemzeit ist um einen Tag versetzt. Bis die Zeit korrigiert wurde, könnten die geplanten Aufgaben nicht korrekt ausgeführt werden",
"UnsavedChanges": "Ungespeicherte Änderungen",
@@ -506,7 +506,7 @@
"ScriptPath": "Script Pfad",
"SetPermissions": "Rechte setzen",
"SetPermissionsLinuxHelpTextWarning": "Ändere diese Einstellung nur, wenn du weißt was sie bewirken.",
"ShouldMonitorHelpText": "Sollen von dieser Liste hinzugefügte Filme oder Sammlungen als beobachtet hinzugefügt werden",
"ShouldMonitorHelpText": "Beobachte Filme die von dieser Liste hinzugefügt wurden",
"ShowAsAllDayEvents": "Als Ganztags Events anzeigen",
"ShowCutoffUnmetIconHelpText": "Symbol zeigen wenn die Qualitätsschwelle noch nicht erreicht wurde",
"ShowMovieInformationHelpText": "Genre und Zertifizierung anzeigen",
@@ -633,14 +633,14 @@
"ShowGenres": "Genres anzeigen",
"ShowCertification": "Zertifikation anzeigen",
"SettingsRuntimeFormat": "Laufzeit Format",
"SearchOnAddHelpText": "Nach Filmen auf dieser Liste suchen, wenn sie der Bibliothek hinzugefügt werden",
"SearchOnAddHelpText": "Suche nach den Filmen auf der Liste nach dem hinzufügen",
"RSSSyncIntervalHelpTextWarning": "Dies wird alle Indexer betreffen. Bitte folge deren Regeln",
"RSSIsNotSupportedWithThisIndexer": "RSS wird von diesem Indexer nicht unterstützt",
"RetryingDownloadInterp": "Herunterladen nochmal versuchen {0} um {1}",
"RemovingTag": "Tag entfernen",
"ReleaseWillBeProcessedInterp": "Release wird verarbeitet {0}",
"Queued": "Eingereiht",
"QualityProfileDeleteConfirm": "Qualitätsprofil '{0}' wirklich löschen",
"QualityProfileDeleteConfirm": "Qualitätsprofil '{0}' wirklich löschen?",
"Pending": "Ausstehend",
"Paused": "Pausiert",
"NegateHelpText": "Wenn aktiviert wird das eigene Format nicht angewendet solange diese {0} Bedingung zutrifft.",
@@ -1047,7 +1047,7 @@
"RemotePathMappingCheckFilesLocalWrongOSPath": "Downloader {0} meldet Dateien in {1}, aber dies ist kein valider {2} Pfad. Überprüfe die Downloader Einstellungen.",
"RemotePathMappingCheckFilesBadDockerPath": "Docker erkannt; Downloader {0} meldet Dateien in {1}, aber dies ist kein valider {2} Pfad. Überprüfe deine Remote-Pfadzuordnungen und die Downloader Einstellungen.",
"RemotePathMappingCheckFilesWrongOSPath": "Downloader {0} meldet Dateien in {1}, aber dies ist kein valider {2} Pfad. Überprüfe deine Remote-Pfadzuordnungen und die Downloader Einstellungen.",
"RemotePathMappingCheckGenericPermissions": "Downloader {0} speichert Downloads in {1}, aber Radarr kann dieses Verzeichnis nicht sehen. Möglicherweise müssen die Verzeichnisrechte angepasst werden.",
"RemotePathMappingCheckGenericPermissions": "Downloader {0} speichert Downloads in {1}, aber Radarr kann dieses Verzeichnis nicht sehen. Möchlicherweise müssen die Verzeichnisrechte angepasst werden.",
"RemotePathMappingCheckWrongOSPath": "Downloader {0} speichert Downloads in {1}, aber dies ist kein valider {2} Pfad. Überprüfe die Remote-Pfadzuordnungen und die Downloader Einstellungen.",
"RemotePathMappingCheckLocalWrongOSPath": "Downloader {0} speichert Downloads in {1}, aber dies ist kein valider {2} Pfad. Überprüfe die Downloader Einstellungen.",
"RemotePathMappingCheckLocalFolderMissing": "Downloader {0} speichert Downloads in {1}, aber dieses Verzeichnis scheint nicht zu existieren. Möglicherweise eine fehlende oder falsche Remote-Pfadzuordnung.",
@@ -1112,35 +1112,9 @@
"OriginalTitle": "Originaler Titel",
"OriginalLanguage": "Originale Sprache",
"Database": "Datenbank",
"AllCollectionsHiddenDueToFilter": "Alle Filme sind auf Grund des Filters ausgeblendet.",
"Collections": "Sammlungen",
"AllCollectionsHiddenDueToFilter": "Alle Filme sind wegen dem Filter ausgeblendet.",
"Collections": "Sammlung",
"MonitorMovies": "Film beobachten",
"NoCollections": "Keine Filme gefunden. Zum Starten solltest du einen Film hinzufügen oder vorhandene Importieren",
"RssSyncHelpText": "Intervall in Minuten. Zum deaktivieren auf 0 setzen ( Dies wird das automatische Release erfassen deaktivieren )",
"CollectionOptions": "Sammlung Optionen",
"ChooseImportMode": "Wähle eine Importmethode",
"CollectionsSelectedInterp": "{0} Ausgewählte Sammlung(en)",
"MovieCollectionMissingRoot": "Fehlender Stammordner für die Filmsammlung: {0}",
"EditCollection": "Sammlung bearbeiten",
"MonitoredCollectionHelpText": "Beobachten zur automatischen Aufnahme von Filmen aus dieser Sammlung in die Bibliothek",
"MovieOnly": "Nur Film",
"ScrollMovies": "Filme scrollen",
"ShowCollectionDetails": "Status der Sammlung anzeigen",
"RefreshCollections": "Sammlungen aktualisieren",
"RefreshMonitoredIntervalHelpText": "Wie häufig die beobachteten Downloads von Download-Clients aktualisiert werden sollen (min. 1 Minute)",
"ShowOverview": "Übersicht anzeigen",
"ShowPosters": "Plakate anzeigen",
"CollectionShowDetailsHelpText": "Status und Eigenschaften der Sammlung anzeigen",
"CollectionShowPostersHelpText": "Poster der Sammlungseinträge zeigen",
"SearchOnAddCollectionHelpText": "Nach Filmen in dieser Sammlung suchen, wenn sie der Bibliothek hinzugefügt werden",
"CollectionShowOverviewsHelpText": "Sammlungsübersichten anzeigen",
"MonitorCollection": "Sammlung beobachten",
"MovieAndCollection": "Film und Sammlung",
"MovieCollectionMultipleMissingRoots": "Es fehlen mehrere Stammordner für Filmsammlungen: {0}",
"OnMovieAdded": "Bei Film hinzugefügt",
"OnMovieAddedHelpText": "Ausführen wenn ein Film hinzugefügt wurde",
"UnableToLoadCollections": "Sammlungen können nicht geladen werden",
"InstanceName": "Instanzname",
"InstanceNameHelpText": "Instanzname im Browser-Tab und für Syslog-Anwendungsname",
"RottenTomatoesRating": "Tomato Bewertung"
"NoCollections": "Keine Filme gefunden. Zum Starten solltest du einen Film hinzufügen oder vorhandene Importieren.",
"RssSyncHelpText": "Intervall in Minuten. Zum deaktivieren auf 0 setzen ( Dies wird das automatische Release erfassen deaktivieren )"
}

View File

@@ -859,7 +859,6 @@
"RootFolderCheckMultipleMessage": "Multiple root folders are missing: {0}",
"RootFolderCheckSingleMessage": "Missing root folder: {0}",
"RootFolders": "Root Folders",
"RottenTomatoesRating": "Tomato Rating",
"RSS": "RSS",
"RSSIsNotSupportedWithThisIndexer": "RSS is not supported with this indexer",
"RSSSync": "RSS Sync",
@@ -1027,7 +1026,6 @@
"Torrents": "Torrents",
"TorrentsDisabled": "Torrents Disabled",
"TotalFileSize": "Total File Size",
"TotalMovies": "Total Movies",
"TotalSpace": "Total Space",
"Trace": "Trace",
"Trailer": "Trailer",

View File

@@ -1115,9 +1115,5 @@
"AllCollectionsHiddenDueToFilter": "Todas las películas están ocultas debido al filtro aplicado.",
"Collections": "Colección",
"MonitorMovies": "Monitorear Película",
"NoCollections": "No se encontraron películas, para comenzar, querrá agregar una nueva película o importar algunas existentes.",
"ChooseImportMode": "Elegir Modo de Importación",
"CollectionOptions": "Opciones de la Colección",
"CollectionShowDetailsHelpText": "Mostrar el estado y propiedades de la colección",
"CollectionShowOverviewsHelpText": "Mostrar resumenes de la colección"
"NoCollections": "No se encontraron películas, para comenzar, querrá agregar una nueva película o importar algunas existentes."
}

View File

@@ -220,7 +220,7 @@
"MoveFiles": "Siirrä tiedostoja",
"MovieFiles": "Elokuvatiedostot",
"MovieIsRecommend": "Elokuvaa suositellaan viimeaikaisen lisäyksen perusteella",
"NextExecution": "Seuraava suoritus",
"NextExecution": "Seuraava toteutus",
"NoAltTitle": "Ei vaihtoehtoisia nimikkeitä.",
"NoEventsFound": "Tapahtumia ei löytynyt",
"NoLinks": "Ei linkkejä",
@@ -320,8 +320,8 @@
"ImportErrors": "Tuontivirheet",
"Imported": "Tuodut",
"InvalidFormat": "Väärä muoto",
"LastDuration": "Edellinen kesto",
"LastExecution": "Edellinen suoritus",
"LastDuration": "Viimeisin kesto",
"LastExecution": "Viimeinen toteutus",
"ListSyncLevelHelpTextWarning": "Elokuvatiedostot poistetaan pysyvästi, mikä voi johtaa kirjaston pyyhkimiseen, jos luettelosi ovat tyhjät",
"ListExclusions": "Listojen poikkeussäännöt",
"Indexer": "Tietolähde",
@@ -425,7 +425,7 @@
"RestartRequiredHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.",
"Restore": "Palauta",
"RestoreBackup": "Palauta varmuuskopio",
"RootFolder": "Juurikansio",
"RootFolder": "Pääkansio",
"RootFolderCheckMultipleMessage": "Useita juurikansioita puuttuu: {0}",
"SendAnonymousUsageData": "Lähetä nimettömiä käyttötietoja",
"Search": "Haku",
@@ -807,7 +807,7 @@
"RetentionHelpText": "Vain Usenet: Aseta nollaan asettamaan rajoittamaton säilytys",
"RetryingDownloadInterp": "Yritetään ladata uudelleen {0} osoitteessa {1}",
"RootFolderCheckSingleMessage": "Puuttuva juurikansio: {0}",
"RootFolders": "Juurikansiot",
"RootFolders": "Pääkansiot",
"RSS": "RSS",
"RSSIsNotSupportedWithThisIndexer": "RSS-syötettä ei ole käytettävissä tälle tietolähteelle",
"RSSSyncInterval": "RSS-synkronointiväli",
@@ -970,7 +970,7 @@
"UnableToLoadRemotePathMappings": "Etäsijaintien kartoitusten lataus epäonnistui.",
"UnableToLoadRestrictions": "Rajoitusten lataus epäonnistui.",
"UnableToLoadResultsIntSearch": "Elokuvahaun tuloksien lataus epäonnistui. Yritä myöhemmin uudelleen.",
"UnableToLoadRootFolders": "Juurikansioiden lataus epäonnistui.",
"UnableToLoadRootFolders": "Pääkansioiden lataus epäonnistui.",
"UnableToLoadTags": "Tunnisteiden lataus epäonnistui.",
"UnableToLoadTheCalendar": "Kalenterin lataus epäonnistui.",
"UnableToUpdateRadarrDirectly": "Radarrin suora päivitys epäonnistui.",
@@ -1041,7 +1041,7 @@
"Reddit": "Reddit",
"More": "Lisää",
"Download": "Lataa",
"DownloadClientCheckDownloadingToRoot": "Lataustyökalu '{0}' sijoittaa lataukset juurikansioon '{1}' ja näin ei pitäisi tehdä, vaan lataukset tulee tallentaa erilliseen sijaintiin.",
"DownloadClientCheckDownloadingToRoot": "Lataustyökalu '{0}' sijoittaa lataukset pääkansioon '{1}' ja näin ei pitäisi tehdä, vaan lataukset tulee tallentaa erilliseen sijaintiin.",
"DeleteFileLabel": "Poista {0} elokuvatiedosto",
"UnableToAddRootFolder": "Juurikansioiden lataus epäonnistui.",
"AreYouSureYouWantToRemoveTheSelectedItemsFromBlocklist": "Haluatko varmasti poistaa valitut kohteet estolistalta?",
@@ -1115,7 +1115,7 @@
"RefreshMonitoredIntervalHelpText": "Miten usein valvottujen latausten tiedot päivitetään lataustyökaluilta (vähimmäisaika on 1 minuutti).",
"RssSyncHelpText": "Aikaväli minuutteina. Arvo nolla kytkee toiminnon pois käytöstä ja lopettaen samalla automaattisen julkaisujen kaappauksen täysin.",
"InstanceName": "Instanssin nimi",
"InstanceNameHelpText": "Instanssin nimi välilehdellä ja järjestelmälokissa",
"InstanceNameHelpText": "Instanssin nimi välilehdellä ja sovelluksen Syslog-nimeksi",
"AllCollectionsHiddenDueToFilter": "Käytössä oleva suodatin on piilottanut kaikki kokoelmat.",
"Collections": "Kokoelmat",
"MonitorMovies": "Valvo elokuvia",
@@ -1134,13 +1134,5 @@
"ScrollMovies": "Vieritä elokuvia",
"ShowCollectionDetails": "Näytä kokoelman tila",
"ShowOverview": "Näytä yleiskatsaus",
"UnableToLoadCollections": "Kokoelmia ei voitu ladata",
"OnMovieAdded": "Kun elokuva lisätään",
"OnMovieAddedHelpText": "Kun elokuva lisätään",
"ShowPosters": "Näytä julisteet",
"CollectionShowOverviewsHelpText": "Näytä kokoelmien katsaukset",
"CollectionOptions": "Kokoelmien valinnat",
"CollectionShowDetailsHelpText": "Näytä kokoelmien tila ja ominaisuudet",
"CollectionShowPostersHelpText": "Näytä kokoelmien julisteet",
"RottenTomatoesRating": "Tomaattiarvio"
"UnableToLoadCollections": "Kokoelmia ei voitu ladata"
}

View File

@@ -318,7 +318,7 @@
"ChangeHasNotBeenSavedYet": "Les changements n'ont pas encore été sauvegardés",
"ChangeFileDate": "Changer la date du fichier",
"CertificationCountryHelpText": "Choisir un pays pour les classifications de films",
"CertificateValidationHelpText": "Modifier le degré de rigueur de la validation de la certification HTTPS. Ne pas changer à moins que vous ne compreniez les risques.",
"CertificateValidationHelpText": "Change la rigueur de la vérification du certificat HTTPS. Ne changez rien sauf si vous comprenez les risques.",
"CertificateValidation": "Validation du certificat",
"BypassProxyForLocalAddresses": "Contourner le proxy pour les adresses locales",
"Branch": "Branche",
@@ -1119,8 +1119,5 @@
"NoCollections": "Aucun film trouvé, pour commencer, vous voudrez ajouter un nouveau film ou importer des films existants.",
"RssSyncHelpText": "Intervalle en minutes. Mettre à zéro pour désactiver (cela arrêtera tous les téléchargements automatiques)",
"CollectionsSelectedInterp": "{0} Collections(s) Sélectionnée(s)",
"ChooseImportMode": "Mode d'importation",
"CollectionOptions": "Options de collection",
"CollectionShowDetailsHelpText": "Afficher l'état et les propriétés de la collection",
"CollectionShowOverviewsHelpText": "Afficher les aperçus des collections"
"ChooseImportMode": "Mode d'importation"
}

View File

@@ -1133,14 +1133,5 @@
"MonitorCollection": "Gyűjtemény monitorozása",
"SearchOnAddCollectionHelpText": "Ebben a gyűjteményben található filmek keresése, a hozzáadás adás után",
"UnableToLoadCollections": "Nem sikerült betölteni a gyűjteményeket",
"MonitoredCollectionHelpText": "A gyűjteményből származó filmek monitorozása, hogy automatikusan hozzáadódjanak a könyvtárhoz",
"CollectionOptions": "Gyűjtemény baállítások",
"CollectionShowOverviewsHelpText": "Gyűjtemények áttekintésének megjelenítése",
"CollectionShowDetailsHelpText": "A gyűjtemény állapotának és tulajdonságainak megjelenítése",
"CollectionShowPostersHelpText": "Gyűjteményelemek posztereinek megjelenítése",
"OnMovieAdded": "Film hozzáadásakor",
"OnMovieAddedHelpText": "Film hozzáadásakor",
"ShowPosters": "Poszterek megjelenítése",
"InstanceNameHelpText": "Példánynév a böngésző lapon és a syslog alkalmazás neve",
"RottenTomatoesRating": "Tomato Értékelés"
"MonitoredCollectionHelpText": "A gyűjteményből származó filmek monitorozása, hogy automatikusan hozzáadódjanak a könyvtárhoz"
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -177,82 +177,5 @@
"ColonReplacementFormatHelpText": "Endre hvordan Radarr håndterer kolonerstatning",
"ConnectionLostAutomaticMessage": "Radarr vil forsøke å koble til automatisk, eller du kan klikke oppdater nedenfor.",
"ConnectSettingsSummary": "Varslinger, tilkoblinger til mediaservere/avspillere, og tilpassede scripts",
"CopyUsingHardlinksHelpTextWarning": "I blant kan låste filer forhindre å endre navn på filer som blir delt. Du kan midlertidig deaktivere deling og bruke Raddars navnefunksjon for å jobbe rundt dette.",
"Movies": "Film",
"DeleteCustomFormat": "Klon egendefinert format",
"Deleted": "Slett",
"Indexers": "Indeksere",
"Queued": "Kø",
"Title": "Tittel",
"Updates": "Oppdater",
"Lists": "Liste",
"Search": "Søk",
"Titles": "Tittel",
"Password": "Passord",
"Peers": "Likemenn",
"Port": "Port",
"Posters": "Plakater",
"Protocol": "Protokoll",
"Quality": "kvalitet",
"QualityProfile": "Kvaltietsprofil",
"Ratings": "Vurdering",
"Refresh": "Oppdater",
"Reload": "Likemenn",
"Remove": "Slett",
"Replace": "Erstatt",
"Required": "Kreve",
"Restrictions": "Begrensning",
"RootFolder": "Rotmappe",
"RootFolders": "Rotmappe",
"Runtime": "Kjøretid",
"Scheduled": "Planlagt",
"Seeders": "Delere",
"Settings": "Innstillinger",
"SettingsRemotePathMappingLocalPath": "Lokal sti",
"Torrents": "Torrents",
"Trakt": "Trakt",
"URLBase": "URL Base",
"Username": "Brukernavn",
"Delete": "Slett",
"Info": "Info",
"LocalPath": "Lokal sti",
"Usenet": "Usenet",
"QualityProfiles": "Kvaltietsprofil",
"Queue": "Kø",
"Rating": "Vurdering",
"UI": "Grensesnitt",
"UpdateMechanismHelpText": "Bruk Prowlarrs innebygde oppdaterer eller et skript",
"RSS": "RSS",
"DelayProfile": "Utsetningsprofil",
"DelayProfiles": "Utsetningsprofil",
"Enable": "Aktiver",
"Enabled": "Aktiver",
"Events": "Hendelse",
"Files": "Fil",
"Filter": "Filter",
"Filters": "Filtre",
"Formats": "Format",
"Grab": "Hent",
"Host": "Vert",
"Hostname": "Vertsnavn",
"ICalFeed": "iCal Feed",
"iCalLink": "iCal Link",
"IMDb": "IMDb",
"Indexer": "Indekser",
"Metadata": "metadata",
"Movie": "Film",
"Crew": "Besetning",
"Details": "detaljer",
"RecyclingBin": "Papirkurv",
"Custom": "Tilpass",
"CustomFormat": "Egendefinert format",
"CustomFormats": "Egendefinert format",
"Cutoff": "Avskjæring",
"Disabled": "deaktivert",
"DownloadClient": "Nedlastingsklient",
"DownloadClients": "Nedlastingsklient",
"Language": "språk",
"List": "Liste",
"New": "Ny",
"RemotePathMappings": "Ekstern portmapping"
"CopyUsingHardlinksHelpTextWarning": "I blant kan låste filer forhindre å endre navn på filer som blir delt. Du kan midlertidig deaktivere deling og bruke Raddars navnefunksjon for å jobbe rundt dette."
}

View File

@@ -246,10 +246,10 @@
"ImportMechanismHealthCheckMessage": "Włącz obsługę ukończonego pobierania",
"IndexersSettingsSummary": "Indeksatory i ograniczenia dotyczące wersji",
"InvalidFormat": "Niepoprawny format",
"ChmodFolder": "chmod Folderu",
"ChmodFolder": "chmod Folder",
"ChmodFolderHelpText": "Ósemkowy, stosowany podczas importu / zmiany nazwy do folderów multimedialnych i plików (bez bitów wykonania)",
"ChmodFolderHelpTextWarning": "Działa to tylko wtedy, gdy użytkownik uruchamiający Radarr jest właścicielem pliku. Lepiej jest upewnić się, że klient pobierania prawidłowo ustawia uprawnienia.",
"ChmodGroup": "chmod Grupy",
"ChmodGroup": "chmod Group",
"ChmodGroupHelpText": "Nazwa grupy lub identyfikator. Użyj gid dla zdalnych systemów plików.",
"ChmodGroupHelpTextWarning": "Działa to tylko wtedy, gdy użytkownik uruchamiający Radarr jest właścicielem pliku. Lepiej jest upewnić się, że klient pobierania używa tej samej grupy co Radarr.",
"ListSyncLevelHelpTextWarning": "Pliki filmowe zostaną trwale usunięte, co może spowodować wyczyszczenie biblioteki, jeśli listy są puste",
@@ -259,7 +259,7 @@
"Medium": "Średni",
"Minutes": "Minuty",
"ListExclusions": "Wykluczenia z listy",
"MissingFromDisk": "Radarr nie mógł znaleźć pliku na dysku, więc został odłączony od filmu w bazie danych",
"MissingFromDisk": "Radarr nie mógł znaleźć pliku na dysku, więc został odłączony od filmu w bazie danych.",
"Monday": "poniedziałek",
"MoveFiles": "Przenieś pliki",
"MovieIsRecommend": "Film jest zalecany na podstawie niedawnego dodania",
@@ -484,8 +484,8 @@
"ClickToChangeMovie": "Kliknij, aby zmienić film",
"ClickToChangeQuality": "Kliknij, aby zmienić jakość",
"CloneCustomFormat": "Klonuj format niestandardowy",
"CloneFormatTag": "Klonuj Tag Formatu",
"CloneIndexer": "Sklonuj Indekser",
"CloneFormatTag": "Clone Format Tag",
"CloneIndexer": "Clone Indexer",
"CloneProfile": "Klonuj profil",
"Close": "Blisko",
"ColonReplacement": "Wymiana okrężnicy",
@@ -497,7 +497,7 @@
"Connection": "Połączenie",
"ConnectionLost": "Utracono połączenie",
"ConnectionLostAutomaticMessage": "Radarr spróbuje połączyć się automatycznie lub możesz kliknąć przycisk przeładuj poniżej.",
"ConnectionLostMessage": "Radarr utracił połączenie z silnikiem programu, aby przywrócić funkcjonalność musi zostać zrestartowany.",
"ConnectionLostMessage": "Radarr utracił połączenie z zapleczem i będzie musiał zostać ponownie załadowany, aby przywrócić funkcjonalność.",
"Connections": "Znajomości",
"ConnectSettings": "Ustawienia połączenia",
"ConnectSettingsSummary": "Powiadomienia, połączenia z serwerami / odtwarzaczami multimedialnymi i niestandardowe skrypty",
@@ -545,7 +545,7 @@
"DeleteRestrictionHelpText": "Czy na pewno chcesz usunąć to ograniczenie?",
"DeleteSelectedMovie": "Usuń wybrane filmy",
"DeleteTagMessageText": "Czy na pewno chcesz usunąć tag „{0}”?",
"DeleteTheMovieFolder": "Folder '{0}' i cała jego zawartość zostaną usunięte.",
"DeleteTheMovieFolder": "Folder filmów „{0} i cała jego zawartość zostaną usunięte.",
"DestinationPath": "Ścieżka docelowa",
"DestinationRelativePath": "Względna ścieżka celu",
"DetailedProgressBar": "Szczegółowy pasek postępu",
@@ -570,7 +570,7 @@
"DownloadFailed": "Pobieranie nie udane",
"DownloadFailedInterp": "Pobieranie nie powiodło się: {0}",
"Downloading": "Ściąganie",
"DownloadPropersAndRepacks": "Poprawione i przepakowane",
"DownloadPropersAndRepacks": "Propers and Repacks",
"DownloadPropersAndRepacksHelpTextWarning": "Użyj niestandardowych formatów do automatycznej aktualizacji do Propers / Repacks",
"DownloadWarningCheckDownloadClientForMoreDetails": "Ostrzeżenie dotyczące pobierania: sprawdź klienta pobierania, aby uzyskać więcej informacji",
"Edition": "Wydanie",
@@ -638,8 +638,8 @@
"GoToInterp": "Idź do {0}",
"Grab": "Chwycić",
"Grabbed": "Złapał",
"GrabID": "Pobierz ID",
"GrabRelease": "Pobierz Wydanie",
"GrabID": "Grab ID",
"GrabRelease": "Grab Release",
"GrabReleaseMessageText": "Radarr nie był w stanie określić, dla którego filmu jest to wydanie. Radarr może nie być w stanie automatycznie zaimportować tej wersji. Czy chcesz złapać „{0}”?",
"GrabSelected": "Wybierz wybrane",
"Group": "Grupa",
@@ -650,7 +650,7 @@
"HideAdvanced": "Ukryj zaawansowane",
"History": "Historia",
"Host": "Gospodarz",
"iCalLink": "Łącze do iCal",
"iCalLink": "iCal Link",
"IconForCutoffUnmet": "Ikona Cutoff Unmet",
"IgnoredAddresses": "Ignorowane adresy",
"IgnoreDeletedMovies": "Nie monitoruj usuniętych filmów",
@@ -669,7 +669,7 @@
"IncludeUnknownMovieItemsHelpText": "Pokaż elementy bez filmu w kolejce. Może to obejmować usunięte filmy lub cokolwiek innego w kategorii Radarr",
"ImportMovies": "Importuj filmy",
"IndexerPriority": "Priorytet indeksatora",
"IndexerPriorityHelpText": "Priorytet indeksera od 1 (najwyższy) do 50 (najniższy). Domyślnie: 25. Używany podczas pobierania wydań przy wystąpieniu równoważnych wydań. Przy synchronizacji RSS i wyszukiwaniu, Radarr wciąż będzie korzystał ze wszystkich indekserów",
"IndexerPriorityHelpText": "Priorytet indeksera od 1 (najwyższy) do 50 (najniższy). Domyślnie: 25. Używany podczas pobierania wydań przy wystąpieniu równoważnych wydań. Przy synchronizacji RSS i wyszukiwaniu, Radarr wciąż będzie korzystał ze wszystkich indekserów.",
"Indexers": "Indeksatory",
"IndexerSearchCheckNoAutomaticMessage": "Brak dostępnych indeksatorów z włączoną funkcją automatycznego wyszukiwania, Radarr nie zapewni żadnych automatycznych wyników wyszukiwania",
"IndexerSearchCheckNoAvailableIndexersMessage": "Wszystkie indeksatory z możliwością wyszukiwania są tymczasowo niedostępne z powodu ostatnich błędów indeksatora",
@@ -701,7 +701,7 @@
"Logs": "Dzienniki",
"LookingForReleaseProfiles1": "Szukasz profili wersji? Próbować",
"LookingForReleaseProfiles2": "zamiast.",
"LowerCase": "Z małej litery",
"LowerCase": "Małe litery",
"ManualImportSelectLanguage": "Import ręczny - wybierz język",
"ManualImportSelectMovie": "Import ręczny - wybierz film",
"MappedDrivesRunningAsService": "Zmapowane dyski sieciowe nie są dostępne, gdy działają jako usługa systemu Windows. Więcej informacji można znaleźć w FAQ",
@@ -740,7 +740,7 @@
"MovieInvalidFormat": "Film: nieprawidłowy format",
"MultiLanguage": "Wielojęzyczny",
"Negate": "Negować",
"Negated": "Zanegowane",
"Negated": "Negated",
"NoListRecommendations": "Nie znaleziono żadnych pozycji na liście ani rekomendacji. Aby rozpocząć, musisz dodać nowy film, zaimportować istniejące lub dodać listę.",
"NoTagsHaveBeenAddedYet": "Żadne tagi nie zostały jeszcze dodane",
"Options": "Opcje",
@@ -828,16 +828,16 @@
"RSSSync": "Synchronizacja RSS",
"RSSSyncInterval": "Częstotliwość synchronizacji RSS",
"RSSSyncIntervalHelpTextWarning": "Dotyczy to wszystkich indeksujących, prosimy o przestrzeganie zasad przez nich określonych",
"Runtime": "Długość",
"Runtime": "Runtime",
"Save": "Zapisać",
"SaveChanges": "Zapisz zmiany",
"SaveSettings": "Zapisz ustawienia",
"Scheduled": "Planowy",
"Score": "Wynik",
"Script": "Scenariusz",
"ScriptPath": "Ścieżka do Skryptu",
"ScriptPath": "Script Path",
"SearchAll": "Wyszukaj wszystko",
"SearchCutoffUnmet": "Niespełnione Parametry Wyszukiwania",
"SearchCutoffUnmet": "Search Cutoff Unmet",
"SearchFailedPleaseTryAgainLater": "Wyszukiwanie nie powiodło się, spróbuj ponownie później.",
"SearchFiltered": "Szukaj przefiltrowane",
"SearchForMissing": "Wyszukaj brakujące",
@@ -893,7 +893,7 @@
"Shutdown": "Zamknąć",
"SizeOnDisk": "Rozmiar dysku",
"SkipFreeSpaceCheck": "Pomiń sprawdzanie wolnego miejsca",
"SkipFreeSpaceCheckWhenImportingHelpText": "Zaznacz, jeśli Radarr nie będzie wstanie wykryć ilości wolnego miejsca w główny folderze filmów",
"SkipFreeSpaceCheckWhenImportingHelpText": "Użyj, gdy Radarr nie może wykryć wolnego miejsca w folderze głównym filmu",
"Small": "Mały",
"Socks4": "Skarpetki 4",
"Socks5": "Socks5 (Wsparcie TOR)",
@@ -932,10 +932,10 @@
"Time": "Czas",
"Title": "Tytuł",
"Titles": "Tytuły",
"TMDBId": "Identyfikator TMDb",
"TMDBId": "TMDb Id",
"TmdbIdHelpText": "Identyfikator TMDb filmu do wykluczenia",
"Today": "Dzisiaj",
"TorrentDelay": "Opóźnienie Torrenta",
"TorrentDelay": "Torrent Delay",
"TorrentDelayHelpText": "Opóźnienie w ciągu kilku minut, aby poczekać przed złapaniem torrenta",
"Torrents": "Torrenty",
"TorrentsDisabled": "Torrenty wyłączone",
@@ -946,7 +946,7 @@
"Type": "Rodzaj",
"UI": "UI",
"UILanguage": "Język interfejsu użytkownika",
"UILanguageHelpText": "Język, interfejsu użytkownika używanego przez Radarr",
"UILanguageHelpText": "Język, którego Radarr będzie używać w interfejsie użytkownika",
"UILanguageHelpTextWarning": "Wymagane przeładowanie przeglądarki",
"UISettings": "Ustawienia interfejsu użytkownika",
"UISettingsSummary": "Opcje z osłabionym kalendarzem, datą i kolorem",
@@ -989,7 +989,7 @@
"UnsavedChanges": "Niezapisane zmiany",
"UnselectAll": "Odznacz wszystko",
"UpdateAll": "Aktualizuj wszystko",
"UpperCase": "Z dużej litery",
"UpperCase": "Duże litery",
"UpdateCheckUINotWritableMessage": "Nie można zainstalować aktualizacji, ponieważ użytkownik „{1}” nie ma prawa zapisu w folderze interfejsu użytkownika „{0}”.",
"UpdateMechanismHelpText": "Użyj wbudowanego aktualizatora Radarr lub skryptu",
"UpdateScriptPathHelpText": "Ścieżka do niestandardowego skryptu, który pobiera wyodrębniony pakiet aktualizacji i obsługuje pozostałą część procesu aktualizacji",
@@ -1006,7 +1006,7 @@
"VisitGithubCustomFormatsAphrodite": "Odwiedź wiki, aby uzyskać więcej informacji: ",
"WaitingToProcess": "Czekam na przetworzenie",
"Wanted": "Chciał",
"Warn": "Ostrzeż",
"Warn": "Ostrzec",
"Week": "Tydzień",
"WeekColumnHeader": "Nagłówek kolumny tygodnia",
"Weeks": "Tygodni",
@@ -1043,25 +1043,25 @@
"Download": "Ściągnij",
"DownloadClientCheckDownloadingToRoot": "Klient pobierania {0} umieszcza pliki do pobrania w folderze głównym {1}. Nie należy pobierać do folderu głównego.",
"DeleteFileLabel": "Usuń {0} pliki filmowe",
"UnableToAddRootFolder": "Nie można dodać folderu głównego",
"UnableToAddRootFolder": "Nie można załadować folderów głównych",
"AreYouSureYouWantToRemoveTheSelectedItemsFromBlocklist": "Czy na pewno chcesz usunąć wybrane elementy z czarnej listy?",
"Blocklist": "Czarna lista",
"BlocklistRelease": "Wydanie czarnej listy",
"RemoveFromBlocklist": "Usuń z czarnej listy",
"UnableToLoadBlocklist": "Nie można załadować listy blokowania",
"UnableToLoadBlocklist": "Nie można załadować czarnej listy",
"Blocklisted": "Czarna lista",
"AreYouSureYouWantToRemoveSelectedItemFromQueue": "Czy na pewno chcesz usunąć {0} element {1} z kolejki?",
"BlocklistReleases": "Wydanie czarnej listy",
"Filters": "Filtry",
"Filters": "Filtr",
"LocalPath": "Ścieżka lokalna",
"List": "Lista",
"Rating": "Ocena",
"RemotePath": "Ścieżka zdalna",
"List": "Listy",
"Rating": "Oceny",
"RemotePath": "Zdalna ścieżka",
"SelectLanguages": "Wybierz język",
"AllCollectionsHiddenDueToFilter": "Wszystkie kolekcje są ukryte ze względu na zastosowany filtr.",
"Collections": "Kolekcje",
"Collections": "Kolekcja",
"RssSyncHelpText": "Odstęp w minutach. Ustaw na zero, aby wyłączyć (zatrzyma to wszystkie automatyczne przechwytywanie zwolnień)",
"NoCollections": "Nie znaleziono żadnych filmów. Aby rozpocząć, musisz dodać nowy film lub zaimportować istniejące",
"NoCollections": "Nie znaleziono żadnych filmów. Aby rozpocząć, musisz dodać nowy film lub zaimportować istniejące.",
"MonitorMovies": "Monitoruj film",
"ClickToChangeReleaseGroup": "Kliknij, by zmienić grupę wydającą",
"RemotePathMappingCheckDownloadPermissions": "Radarr widzi film {0}, lecz nie ma do niego dostępu. Najprawdopodobniej to wynik błędu w uprawnieniach dostępu.",
@@ -1078,7 +1078,7 @@
"ManualImportSetReleaseGroup": "Import ręczny - podaj nazwę grupy",
"Never": "Nigdy",
"RemotePathMappingCheckFilesWrongOSPath": "Zdalny klient pobierania {0} zgłosił pliki w {1}, lecz nie jest to poprawna ścieżka {2}. Zmień ustawienia zdalnego mapowania ścieżek i klienta pobierania.",
"RemotePathMappingCheckGenericPermissions": "Klient pobierania {0} umieszcza pobrane pliki w {1}, lecz Radarr nie widzi tego folderu. Być może należy zmienić uprawnienia dostępu do folderu.",
"RemotePathMappingCheckGenericPermissions": "Klient pobierania {0} umieszcza pobrane pliki w {1}, lecz Radarr nie widzi tego folderu. Być może należy zmienić ustawienia uprawnień dostępu.",
"RemoveFailed": "Usuń nieudane",
"RemoveDownloadsAlert": "Ustawienia usuwania zostały przeniesione do ustawień poszczególnych klientów pobierania powyżej.",
"ShowCollectionDetails": "Pokaż stan kolekcji",
@@ -1092,7 +1092,7 @@
"EditCollection": "Edytuj kolekcję",
"From": "z",
"IndexerTagHelpText": "Korzystaj z tego indeksera wyłącznie w przypadku filmów z co najmniej jednym pasującym tagiem. Pozostaw pole puste, by używać do wszystkich filmów.",
"Letterboxd": "Z Letterboxd",
"Letterboxd": "Letterboxd",
"MonitorCollection": "Monitoruj kolekcję",
"MovieAndCollection": "Film i kolekcja",
"MovieCollectionMissingRoot": "Brak katalogu głównego dla kolekcji filmów: {0}",
@@ -1134,12 +1134,5 @@
"TaskUserAgentTooltip": "User-Agent podawany przez aplikację wywołującą API",
"SetReleaseGroup": "Ustaw grupę wydającą",
"SearchOnAddCollectionHelpText": "Po dodaniu do biblioteki wyszukaj filmy z tej kolekcji",
"Database": "Baza danych",
"OnMovieAddedHelpText": "Przy dodaniu filmu",
"ShowPosters": "Pokaż plakaty",
"OnMovieAdded": "Przy dodaniu filmu",
"CollectionShowPostersHelpText": "Pokaż plakaty elementów kolekcji",
"CollectionOptions": "Opcje Kolekcji",
"CollectionShowDetailsHelpText": "Pokaż status i właściwości kolekcji",
"CollectionShowOverviewsHelpText": "Pokaż przegląd kolekcji"
"Database": "Baza danych"
}

View File

@@ -1116,12 +1116,5 @@
"Collections": "Coleção",
"RssSyncHelpText": "Intervalo em minutos. Defina como zero para desativar (isso parará toda a captura automática)",
"MonitorMovies": "Monitorar filme",
"NoCollections": "Nenhum filme encontrado. Para começar, adiciona um novo filme ou importa alguns já existentes.",
"MovieAndCollection": "Filme e Coleção",
"CollectionsSelectedInterp": "{0} Coleções Selecionadas",
"EditCollection": "Editar Coleção",
"ChooseImportMode": "Selecionar Modo de Importação",
"InstanceName": "Nome da Instancia",
"CollectionOptions": "Opções de Coleção",
"CollectionShowDetailsHelpText": "Mostrar estado da coleção e proprieades"
"NoCollections": "Nenhum filme encontrado. Para começar, adiciona um novo filme ou importa alguns já existentes."
}

View File

@@ -1,5 +1,5 @@
{
"LastExecution": "Última Execução",
"LastExecution": "Execução mais recente",
"Large": "Grande",
"Languages": "Idiomas",
"LanguageHelpText": "Idioma das versões",
@@ -19,7 +19,7 @@
"IndexerStatusCheckAllClientMessage": "Todos os indexadores estão indisponíveis devido a falhas",
"IndexersSettingsSummary": "Indexadores e restrições de lançamento",
"IndexerSettings": "Configurações do indexador",
"IndexerSearchCheckNoInteractiveMessage": "Nenhum indexador disponível com a Pesquisa interativa ativada, o Radarr não fornecerá nenhum resultado de pesquisa interativo",
"IndexerSearchCheckNoInteractiveMessage": "Sem indexadores disponíveis com a Pesquisa Interativa habilitada, o Radarr não fornecerá resultados interativos de pesquisa",
"IndexerSearchCheckNoAvailableIndexersMessage": "Todos os indexadores com capacidade de pesquisa estão temporariamente indisponíveis devido a erros recentes do indexador",
"IndexerSearchCheckNoAutomaticMessage": "Nenhum indexador disponível com a Pesquisa automática habilitada, o Radarr não fornecerá nenhum resultado de pesquisa automática",
"Indexers": "Indexadores",
@@ -571,7 +571,7 @@
"NoChange": "Sem alteração",
"NoBackupsAreAvailable": "Não há backups disponíveis",
"NoAltTitle": "Nenhum título alternativo.",
"NextExecution": "Próxima Execução",
"NextExecution": "Próxima execução",
"New": "Novo",
"NetCore": ".NET",
"ShowAsAllDayEvents": "Mostrar como eventos de dia inteiro",
@@ -668,7 +668,7 @@
"SomeResultsHiddenFilter": "Alguns resultados estão ocultos pelo filtro aplicado",
"Socks5": "Socks5 (suporte ao TOR)",
"Small": "Pequeno",
"SkipFreeSpaceCheckWhenImportingHelpText": "Use quando o Radarr não conseguir detectar espaço livre na pasta raiz do filme",
"SkipFreeSpaceCheckWhenImportingHelpText": "Usar quando o Radarr não conseguir detectar espaço livre da pasta raiz do filme",
"SkipFreeSpaceCheck": "Ignorar verificação de espaço livre",
"SizeOnDisk": "Tamanho em disco",
"Size": "Tamanho",
@@ -961,7 +961,7 @@
"UpdateSelected": "Atualizar selecionado(s)",
"UpdateScriptPathHelpText": "Caminho para um script personalizado que usa um pacote de atualização extraído e lida com o restante do processo de atualização",
"Updates": "Atualizações",
"UpdateMechanismHelpText": "Use o atualizador integrado do Radarr ou um script",
"UpdateMechanismHelpText": "Usar o atualizador embutido do Radarr ou um script",
"UpdateCheckUINotWritableMessage": "Não é possível instalar a atualização porque a pasta de interface do usuário '{0}' não é gravável pelo usuário '{1}'.",
"UpdateCheckStartupTranslocationMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' está em uma pasta App Translocation.",
"UpdateCheckStartupNotWritableMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' não pode ser gravada pelo usuário '{1}'.",
@@ -1053,7 +1053,7 @@
"RemotePathMappingCheckImportFailed": "O Radarr não conseguiu importar um filme. Verifique os logs para saber mais.",
"RemotePathMappingCheckFileRemoved": "O arquivo {0} foi removido no meio do processamento.",
"RemotePathMappingCheckDownloadPermissions": "O Radarr pode ver, mas não pode acessar o filme baixado {0}. Provável erro de permissões.",
"RemotePathMappingCheckGenericPermissions": "O cliente de download {0} coloca downloads em {1} mas o Radarr não pode ver este diretório. Pode ser necessário ajustar as permissões da pasta.",
"RemotePathMappingCheckGenericPermissions": "Cliente para download {0} coloca downloads em {1}, mas o Radarr não pode ver este diretório. Você pode precisar ajustar as permissões da pasta.",
"RemotePathMappingCheckWrongOSPath": "O cliente de download remoto {0} coloca downloads em {1}, mas este não é um caminho {2} válido. Revise seus mapeamentos de caminho remoto e baixe as configurações do cliente.",
"RemotePathMappingCheckLocalWrongOSPath": "O cliente de download local {0} coloca downloads em {1}, mas este não é um caminho {2} válido. Revise as configurações do seu cliente de download.",
"RemotePathMappingCheckLocalFolderMissing": "O cliente de download remoto {0} coloca downloads em {1}, mas esse diretório parece não existir. Mapeamento de caminho remoto provavelmente ausente ou incorreto.",
@@ -1119,7 +1119,7 @@
"AllCollectionsHiddenDueToFilter": "Todos os filmes estão ocultos devido ao filtro aplicado.",
"Collections": "Coleção",
"MonitorMovies": "Monitorar filme",
"NoCollections": "Nenhum filme encontrado. Para começar, adicione um novo filme ou importe alguns existentes",
"NoCollections": "Nenhum filme encontrado. Para começar, adicione um novo filme ou importe alguns existentes.",
"MovieOnly": "Somente Filme",
"UnableToLoadCollections": "Não foi possível carregar as coleções",
"ChooseImportMode": "Escolher o Modo de Importação",
@@ -1134,13 +1134,5 @@
"MonitoredCollectionHelpText": "Monitorar para que os filmes desta coleção sejam adicionados automaticamente à biblioteca",
"RefreshCollections": "Atualizar Coleções",
"SearchOnAddCollectionHelpText": "Pesquisar filmes nesta coleção quando adicionados à biblioteca",
"ScrollMovies": "Rolar Filmes",
"OnMovieAdded": "Ao Filme Adicionado",
"OnMovieAddedHelpText": "Ao Filme Adicionado",
"ShowPosters": "Mostrar pôsteres",
"CollectionOptions": "Opções de Coleção",
"CollectionShowDetailsHelpText": "Mostrar estado e propriedades da coleção",
"CollectionShowOverviewsHelpText": "Mostrar visão geral da coleção",
"CollectionShowPostersHelpText": "Mostrar pôsteres de itens da coleção",
"RottenTomatoesRating": "Avaliação Tomato"
"ScrollMovies": "Rolar Filmes"
}

View File

@@ -110,6 +110,5 @@
"DeleteNotificationMessageText": "Naozaj chcete zmazať značku formátu {0} ?",
"AreYouSureYouWantToRemoveSelectedItemFromQueue": "Naozaj chcete odobrať {0} položku {1} z fronty?",
"ImportCustomFormat": "Pridať vlastný formát",
"DeleteRestrictionHelpText": "Naozaj chcete zmazať tento profil oneskorenia?",
"AllCollectionsHiddenDueToFilter": "Všetky filmy sú skryté kvôli použitému filtru."
"DeleteRestrictionHelpText": "Naozaj chcete zmazať tento profil oneskorenia?"
}

View File

@@ -1134,6 +1134,5 @@
"MovieOnly": "仅电影",
"NoCollections": "没有发现集合,点击添加新的电影或者导入已经存在的电影",
"InstanceNameHelpText": "选项卡及日志应用名称",
"ScrollMovies": "滚动电影",
"CollectionOptions": "Collection Options"
"ScrollMovies": "滚动电影"
}

View File

@@ -1,7 +1,4 @@
{
"About": "關於",
"Add": "添加",
"AcceptConfirmationModal": "接受確認模式",
"Actions": "‎行動‎",
"Activity": "‎活動‎"
"Add": "添加"
}

View File

@@ -91,7 +91,7 @@ namespace NzbDrone.Core.MediaFiles
if (_diskProvider.FolderEmpty(rootFolder))
{
_logger.Warn("Movie's root folder ({0}) is empty. Rescan will not update movies as a failsafe.", rootFolder);
_logger.Warn("Movie's root folder ({0}) is empty.", rootFolder);
_eventAggregator.PublishEvent(new MovieScanSkippedEvent(movie, MovieScanSkippedReason.RootFolderIsEmpty));
return;
}

View File

@@ -5,7 +5,7 @@ using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles.Events
{
public class MovieFileImportedEvent : IEvent
public class MovieImportedEvent : IEvent
{
public LocalMovie MovieInfo { get; private set; }
public MovieFile ImportedMovie { get; private set; }
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.MediaFiles.Events
public DownloadClientItemClientInfo DownloadClientInfo { get; set; }
public string DownloadId { get; private set; }
public MovieFileImportedEvent(LocalMovie movieInfo, MovieFile importedMovie, List<MovieFile> oldFiles, bool newDownload, DownloadClientItem downloadClientItem)
public MovieImportedEvent(LocalMovie movieInfo, MovieFile importedMovie, List<MovieFile> oldFiles, bool newDownload, DownloadClientItem downloadClientItem)
{
MovieInfo = movieInfo;
ImportedMovie = importedMovie;

View File

@@ -61,8 +61,8 @@ namespace NzbDrone.Core.MediaFiles
if (_diskProvider.GetDirectories(rootFolder).Empty())
{
_logger.Warn("Movie's root folder ({0}) is empty. Rescan will not update movies as a failsafe.", rootFolder);
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Movie's root folder ({0}) is empty. Rescan will not update movies as a failsafe.", rootFolder);
_logger.Warn("Movie's root folder ({0}) is empty.", rootFolder);
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Movie's root folder ({0}) is empty.", rootFolder);
}
if (_diskProvider.FolderExists(movie.Path) && _diskProvider.FileExists(fullPath))

View File

@@ -153,10 +153,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return "WMA";
}
Logger.ForDebugEvent()
Logger.Debug()
.Message("Unknown audio format: '{0}' in '{1}'.", mediaInfo.RawStreamData, sceneName)
.WriteSentryWarn("UnknownAudioFormatFFProbe", mediaInfo.ContainerFormat, mediaInfo.AudioFormat, audioCodecID)
.Log();
.Write();
return mediaInfo.AudioFormat;
}
@@ -262,10 +262,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return "";
}
Logger.ForDebugEvent()
Logger.Debug()
.Message("Unknown video format: '{0}' in '{1}'.", mediaInfo.RawStreamData, sceneName)
.WriteSentryWarn("UnknownVideoFormatFFProbe", mediaInfo.ContainerFormat, videoFormat, videoCodecID)
.Log();
.Write();
return result;
}

View File

@@ -144,7 +144,7 @@ namespace NzbDrone.Core.MediaFiles.MovieImport
_extraService.ImportMovie(localMovie, movieFile, copyOnly);
}
_eventAggregator.PublishEvent(new MovieFileImportedEvent(localMovie, movieFile, oldFiles, newDownload, downloadClientItem));
_eventAggregator.PublishEvent(new MovieImportedEvent(localMovie, movieFile, oldFiles, newDownload, downloadClientItem));
}
catch (RootFolderNotFoundException e)
{

View File

@@ -327,13 +327,6 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
}
else if (movie.ImdbId.IsNotNullOrWhiteSpace())
{
newMovie = _movieMetadataService.FindByImdbId(Parser.Parser.NormalizeImdbId(movie.ImdbId));
if (newMovie != null)
{
return newMovie;
}
newMovie = GetMovieByImdbId(movie.ImdbId);
}
else
@@ -344,7 +337,7 @@ namespace NzbDrone.Core.MetadataSource.SkyHook
yearStr = $" {movie.Year}";
}
newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault()?.MovieMetadata ?? null;
newMovie = SearchForNewMovie(movie.Title + yearStr).FirstOrDefault().MovieMetadata;
}
if (newMovie == null)

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies.Events;
@@ -14,7 +13,6 @@ namespace NzbDrone.Core.Movies.Collections
IEnumerable<MovieCollection> GetCollections(IEnumerable<int> ids);
List<MovieCollection> GetAllCollections();
MovieCollection UpdateCollection(MovieCollection collection);
List<MovieCollection> UpdateCollections(List<MovieCollection> collections);
void RemoveCollection(MovieCollection collection);
bool Upsert(MovieCollection collection);
bool UpsertMany(List<MovieCollection> collections);
@@ -25,14 +23,12 @@ namespace NzbDrone.Core.Movies.Collections
private readonly IMovieCollectionRepository _repo;
private readonly IMovieService _movieService;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
public MovieCollectionService(IMovieCollectionRepository repo, IMovieService movieService, IEventAggregator eventAggregator, Logger logger)
public MovieCollectionService(IMovieCollectionRepository repo, IMovieService movieService, IEventAggregator eventAggregator)
{
_repo = repo;
_movieService = movieService;
_eventAggregator = eventAggregator;
_logger = logger;
}
public MovieCollection AddCollection(MovieCollection newCollection)
@@ -77,21 +73,6 @@ namespace NzbDrone.Core.Movies.Collections
return updatedCollection;
}
public List<MovieCollection> UpdateCollections(List<MovieCollection> collections)
{
_logger.Debug("Updating {0} movie collections", collections.Count);
foreach (var c in collections)
{
_logger.Trace("Updating: {0}", c.Title);
}
_repo.UpdateMany(collections);
_logger.Debug("{0} movie collections updated", collections.Count);
return collections;
}
public void RemoveCollection(MovieCollection collection)
{
_repo.Delete(collection);
@@ -122,7 +103,7 @@ namespace NzbDrone.Core.Movies.Collections
var collection = FindByTmdbId(collectionTmdbId);
_repo.Delete(collection.Id);
_repo.Delete(collectionTmdbId);
_eventAggregator.PublishEvent(new CollectionDeletedEvent(collection));
}

View File

@@ -5,11 +5,11 @@ namespace NzbDrone.Core.Movies.Events
{
public class MoviesImportedEvent : IEvent
{
public List<Movie> Movies { get; private set; }
public List<int> MovieIds { get; private set; }
public MoviesImportedEvent(List<Movie> movies)
public MoviesImportedEvent(List<int> movieIds)
{
Movies = movies;
MovieIds = movieIds;
}
}
}

View File

@@ -23,7 +23,7 @@ namespace NzbDrone.Core.Movies
public void Handle(MoviesImportedEvent message)
{
_commandQueueManager.PushMany(message.Movies.Select(s => new RefreshMovieCommand(new List<int> { s.Id }, true)).ToList());
_commandQueueManager.PushMany(message.MovieIds.Select(s => new RefreshMovieCommand(new List<int> { s }, true)).ToList());
}
}
}

View File

@@ -11,7 +11,6 @@ namespace NzbDrone.Core.Movies
public interface IMovieMetadataRepository : IBasicRepository<MovieMetadata>
{
MovieMetadata FindByTmdbId(int tmdbId);
MovieMetadata FindByImdbId(string imdbId);
List<MovieMetadata> FindById(List<int> tmdbIds);
List<MovieMetadata> GetMoviesWithCollections();
List<MovieMetadata> GetMoviesByCollectionTmdbId(int collectionId);
@@ -28,14 +27,9 @@ namespace NzbDrone.Core.Movies
_logger = logger;
}
public MovieMetadata FindByTmdbId(int tmdbId)
public MovieMetadata FindByTmdbId(int tmdbid)
{
return Query(x => x.TmdbId == tmdbId).FirstOrDefault();
}
public MovieMetadata FindByImdbId(string imdbId)
{
return Query(x => x.ImdbId == imdbId).FirstOrDefault();
return Query(x => x.TmdbId == tmdbid).FirstOrDefault();
}
public List<MovieMetadata> FindById(List<int> tmdbIds)

View File

@@ -5,8 +5,7 @@ namespace NzbDrone.Core.Movies
public interface IMovieMetadataService
{
MovieMetadata Get(int id);
MovieMetadata FindByTmdbId(int tmdbId);
MovieMetadata FindByImdbId(string imdbId);
MovieMetadata FindByTmdbId(int tmdbid);
List<MovieMetadata> GetMoviesWithCollections();
List<MovieMetadata> GetMoviesByCollectionTmdbId(int collectionId);
bool Upsert(MovieMetadata movie);
@@ -22,14 +21,9 @@ namespace NzbDrone.Core.Movies
_movieMetadataRepository = movieMetadataRepository;
}
public MovieMetadata FindByTmdbId(int tmdbId)
public MovieMetadata FindByTmdbId(int tmdbid)
{
return _movieMetadataRepository.FindByTmdbId(tmdbId);
}
public MovieMetadata FindByImdbId(string imdbId)
{
return _movieMetadataRepository.FindByImdbId(imdbId);
return _movieMetadataRepository.FindByTmdbId(tmdbid);
}
public List<MovieMetadata> GetMoviesWithCollections()

View File

@@ -100,7 +100,7 @@ namespace NzbDrone.Core.Movies
{
_movieRepository.InsertMany(newMovies);
_eventAggregator.PublishEvent(new MoviesImportedEvent(newMovies));
_eventAggregator.PublishEvent(new MoviesImportedEvent(newMovies.Select(s => s.Id).ToList()));
return newMovies;
}

View File

@@ -3,22 +3,22 @@ using System.Linq;
using NLog;
using NzbDrone.Common.Instrumentation.Extensions;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.ImportLists.ImportExclusions;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Movies.Collections;
using NzbDrone.Core.Movies.Commands;
using NzbDrone.Core.Movies.Events;
namespace NzbDrone.Core.Movies
{
public class RefreshCollectionService : IExecute<RefreshCollectionsCommand>
public class RefreshCollectionService : IExecute<RefreshCollectionsCommand>, IHandle<CollectionEditedEvent>
{
private readonly IProvideMovieInfo _movieInfo;
private readonly IMovieCollectionService _collectionService;
private readonly IMovieService _movieService;
private readonly IMovieMetadataService _movieMetadataService;
private readonly IAddMovieService _addMovieService;
private readonly IImportExclusionsService _importExclusionService;
private readonly Logger _logger;
@@ -27,7 +27,6 @@ namespace NzbDrone.Core.Movies
IMovieService movieService,
IMovieMetadataService movieMetadataService,
IAddMovieService addMovieService,
IImportExclusionsService importExclusionsService,
Logger logger)
{
_movieInfo = movieInfo;
@@ -35,7 +34,6 @@ namespace NzbDrone.Core.Movies
_movieService = movieService;
_movieMetadataService = movieMetadataService;
_addMovieService = addMovieService;
_importExclusionService = importExclusionsService;
_logger = logger;
}
@@ -101,26 +99,21 @@ namespace NzbDrone.Core.Movies
{
var existingMovies = _movieService.AllMovieTmdbIds();
var collectionMovies = _movieMetadataService.GetMoviesByCollectionTmdbId(collection.TmdbId);
var excludedMovies = _importExclusionService.GetAllExclusions().Select(e => e.TmdbId);
var moviesToAdd = collectionMovies.Where(m => !existingMovies.Contains(m.TmdbId)).Where(m => !excludedMovies.Contains(m.TmdbId));
if (moviesToAdd.Any())
_addMovieService.AddMovies(collectionMovies.Where(m => !existingMovies.Contains(m.TmdbId)).Select(m => new Movie
{
_addMovieService.AddMovies(moviesToAdd.Select(m => new Movie
TmdbId = m.TmdbId,
Title = m.Title,
ProfileId = collection.QualityProfileId,
RootFolderPath = collection.RootFolderPath,
MinimumAvailability = collection.MinimumAvailability,
AddOptions = new AddMovieOptions
{
TmdbId = m.TmdbId,
Title = m.Title,
ProfileId = collection.QualityProfileId,
RootFolderPath = collection.RootFolderPath,
MinimumAvailability = collection.MinimumAvailability,
AddOptions = new AddMovieOptions
{
SearchForMovie = collection.SearchOnAdd,
AddMethod = AddMovieMethod.Collection
},
Monitored = true
}).ToList());
}
SearchForMovie = collection.SearchOnAdd,
AddMethod = AddMovieMethod.Collection
},
Monitored = true
}).ToList());
}
}
@@ -158,5 +151,10 @@ namespace NzbDrone.Core.Movies
}
}
}
public void Handle(CollectionEditedEvent message)
{
SyncCollectionMovies(message.Collection);
}
}
}

View File

@@ -140,7 +140,7 @@ namespace NzbDrone.Core.Movies
SearchOnAdd = movie.AddOptions?.SearchForMovie ?? false,
QualityProfileId = movie.ProfileId,
MinimumAvailability = movie.MinimumAvailability,
RootFolderPath = _folderService.GetBestRootFolderPath(movie.Path).TrimEnd('/', '\\', ' ')
RootFolderPath = _folderService.GetBestRootFolderPath(movie.Path)
});
movieMetadata.CollectionTmdbId = newCollection.TmdbId;

View File

@@ -1,4 +1,5 @@
using System;
using NzbDrone.Core.Update;
namespace NzbDrone.Core.Notifications
{
@@ -7,6 +8,7 @@ namespace NzbDrone.Core.Notifications
public string Message { get; set; }
public Version PreviousVersion { get; set; }
public Version NewVersion { get; set; }
public UpdateChanges Changes { get; set; }
public override string ToString()
{

View File

@@ -212,6 +212,16 @@ namespace NzbDrone.Core.Notifications.CustomScript
environmentVariables.Add("Radarr_Update_NewVersion", updateMessage.NewVersion.ToString());
environmentVariables.Add("Radarr_Update_PreviousVersion", updateMessage.PreviousVersion.ToString());
if (updateMessage.Changes.New.Any())
{
environmentVariables.Add("Radarr_Update_NewChanges", string.Join("|", updateMessage.Changes.New.Select(e => e)));
}
if (updateMessage.Changes.Fixed.Any())
{
environmentVariables.Add("Radarr_Update_FixedChanges", string.Join("|", updateMessage.Changes.Fixed.Select(e => e)));
}
ExecuteScript(environmentVariables);
}

View File

@@ -317,6 +317,16 @@ namespace NzbDrone.Core.Notifications.Discord
{
Name = "New Version",
Value = updateMessage.NewVersion.ToString()
},
new DiscordField()
{
Name = "New",
Value = string.Format("```{0}```", string.Join(Environment.NewLine, updateMessage.Changes.New))
},
new DiscordField()
{
Name = "Fixed",
Value = string.Format("```{0}```", string.Join(Environment.NewLine, updateMessage.Changes.Fixed))
}
},
}

View File

@@ -6,7 +6,6 @@ using System.Linq;
using FluentValidation.Results;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.HealthCheck;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Movies;
namespace NzbDrone.Core.Notifications.Notifiarr
@@ -48,8 +47,6 @@ namespace NzbDrone.Core.Notifications.Notifiarr
variables.Add("Radarr_Download_Client", message.DownloadClientName ?? string.Empty);
variables.Add("Radarr_Download_Client_Type", message.DownloadClientType ?? string.Empty);
variables.Add("Radarr_Download_Id", message.DownloadId ?? string.Empty);
variables.Add("Radarr_Release_CustomFormat", string.Join("|", remoteMovie.CustomFormats));
variables.Add("Radarr_Release_CustomFormatScore", remoteMovie.CustomFormatScore.ToString());
_proxy.SendNotification(variables, Settings);
}
@@ -80,15 +77,6 @@ namespace NzbDrone.Core.Notifications.Notifiarr
variables.Add("Radarr_MovieFile_SceneName", movieFile.SceneName ?? string.Empty);
variables.Add("Radarr_MovieFile_SourcePath", sourcePath);
variables.Add("Radarr_MovieFile_SourceFolder", Path.GetDirectoryName(sourcePath));
variables.Add("Radarr_MovieFile_MediaInfo_AudioChannels", MediaInfoFormatter.FormatAudioChannels(movieFile.MediaInfo).ToString());
variables.Add("Radarr_MovieFile_MediaInfo_AudioCodec", MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, null));
variables.Add("Radarr_MovieFile_MediaInfo_AudioLanguages", movieFile.MediaInfo.AudioLanguages.Distinct().ConcatToString(" / "));
variables.Add("Radarr_MovieFile_MediaInfo_Languages", movieFile.MediaInfo.AudioLanguages.ConcatToString(" / "));
variables.Add("Radarr_MovieFile_MediaInfo_Height", movieFile.MediaInfo.Height.ToString());
variables.Add("Radarr_MovieFile_MediaInfo_Width", movieFile.MediaInfo.Width.ToString());
variables.Add("Radarr_MovieFile_MediaInfo_Subtitles", movieFile.MediaInfo.Subtitles.ConcatToString(" / "));
variables.Add("Radarr_MovieFile_MediaInfo_VideoCodec", MediaInfoFormatter.FormatVideoCodec(movieFile.MediaInfo, null));
variables.Add("Radarr_MovieFile_MediaInfo_VideoDynamicRangeType", MediaInfoFormatter.FormatVideoDynamicRangeType(movieFile.MediaInfo));
variables.Add("Radarr_Download_Id", message.DownloadId ?? string.Empty);
variables.Add("Radarr_Download_Client", message.DownloadClientInfo?.Name ?? string.Empty);
variables.Add("Radarr_Download_Client_Type", message.DownloadClientInfo?.Type ?? string.Empty);
@@ -188,6 +176,16 @@ namespace NzbDrone.Core.Notifications.Notifiarr
variables.Add("Radarr_Update_NewVersion", updateMessage.NewVersion.ToString());
variables.Add("Radarr_Update_PreviousVersion", updateMessage.PreviousVersion.ToString());
if (updateMessage.Changes.New.Any())
{
variables.Add("Radarr_Update_NewChanges", string.Join("|", updateMessage.Changes.New.Select(e => e)));
}
if (updateMessage.Changes.Fixed.Any())
{
variables.Add("Radarr_Update_FixedChanges", string.Join("|", updateMessage.Changes.Fixed.Select(e => e)));
}
_proxy.SendNotification(variables, Settings);
}

View File

@@ -54,19 +54,17 @@ namespace NzbDrone.Core.Notifications.Notifiarr
_logger.Error(ex, "API key is invalid: " + ex.Message);
return new ValidationFailure("APIKey", "API key is invalid");
case 400:
_logger.Error(ex, "Unable to send test message. Ensure Radarr Integration is enabled & assigned a channel on Notifiarr");
return new ValidationFailure("", "Unable to send test message. Ensure Radarr Integration is enabled & assigned a channel on Notifiarr");
case 520:
case 521:
case 522:
case 523:
case 524:
_logger.Error(ex, "Cloudflare Related HTTP Error - Unable to send test message: " + ex.Message);
return new ValidationFailure("", "Cloudflare Related HTTP Error - Unable to send test message");
_logger.Error(ex, "Unable to send test notification: " + ex.Message);
return new ValidationFailure("", "Unable to send test notification");
}
_logger.Error(ex, "Unknown HTTP Error - Unable to send test message: " + ex.Message);
return new ValidationFailure("", "Unknown HTTP Error - Unable to send test message");
_logger.Error(ex, "Unable to send test message: " + ex.Message);
return new ValidationFailure("APIKey", "Unable to send test notification");
}
catch (Exception ex)
{
@@ -80,7 +78,8 @@ namespace NzbDrone.Core.Notifications.Notifiarr
try
{
var url = settings.Environment == (int)NotifiarrEnvironment.Development ? "https://dev.notifiarr.com" : "https://notifiarr.com";
var requestBuilder = new HttpRequestBuilder(url + "/api/v1/notification/radarr/" + settings.APIKey).Post();
var requestBuilder = new HttpRequestBuilder(url + "/notifier.php").Post();
requestBuilder.AddFormParameter("api", settings.APIKey).Build();
requestBuilder.AddFormParameter("instanceName", settings.InstanceName).Build();
foreach (string key in message.Keys)
@@ -97,21 +96,19 @@ namespace NzbDrone.Core.Notifications.Notifiarr
switch ((int)ex.Response.StatusCode)
{
case 401:
_logger.Error("", "API key is invalid");
throw new NotifiarrException("API key is invalid", ex);
_logger.Error(ex, "API key is invalid");
throw;
case 400:
_logger.Error(ex, "Unable to send notification. Ensure Radarr Integration is enabled & assigned a channel on Notifiarr");
throw new NotifiarrException("Unable to send notification. Ensure Radarr Integration is enabled & assigned a channel on Notifiarr", ex);
case 520:
case 521:
case 522:
case 523:
case 524:
_logger.Error(ex, "Cloudflare Related HTTP Error - Unable to send notification");
throw new NotifiarrException("Cloudflare Related HTTP Error - Unable to send notification", ex);
_logger.Error(ex, "Unable to send notification");
throw;
}
throw new NotifiarrException("Unknown HTTP Error - Unable to send notification", ex);
throw new NotifiarrException("Unable to send notification", ex);
}
}
}

View File

@@ -85,7 +85,6 @@ namespace NzbDrone.Core.Notifications
definition.SupportsOnDownload = provider.SupportsOnDownload;
definition.SupportsOnUpgrade = provider.SupportsOnUpgrade;
definition.SupportsOnRename = provider.SupportsOnRename;
definition.SupportsOnMovieAdded = provider.SupportsOnMovieAdded;
definition.SupportsOnMovieDelete = provider.SupportsOnMovieDelete;
definition.SupportsOnMovieFileDelete = provider.SupportsOnMovieFileDelete;
definition.SupportsOnMovieFileDeleteForUpgrade = provider.SupportsOnMovieFileDeleteForUpgrade;

View File

@@ -17,10 +17,9 @@ namespace NzbDrone.Core.Notifications
public class NotificationService
: IHandle<MovieRenamedEvent>,
IHandle<MovieGrabbedEvent>,
IHandle<MovieFileImportedEvent>,
IHandle<MovieImportedEvent>,
IHandle<MoviesDeletedEvent>,
IHandle<MovieAddedEvent>,
IHandle<MoviesImportedEvent>,
IHandle<MovieFileDeletedEvent>,
IHandle<HealthCheckFailedEvent>,
IHandle<UpdateInstalledEvent>,
@@ -120,7 +119,7 @@ namespace NzbDrone.Core.Notifications
}
}
public void Handle(MovieFileImportedEvent message)
public void Handle(MovieImportedEvent message)
{
if (!message.NewDownload)
{
@@ -175,27 +174,6 @@ namespace NzbDrone.Core.Notifications
}
}
public void Handle(MoviesImportedEvent message)
{
foreach (var notification in _notificationFactory.OnMovieAddedEnabled())
{
try
{
foreach (var movie in message.Movies)
{
if (ShouldHandleMovie(notification.Definition, movie))
{
notification.OnMovieAdded(movie);
}
}
}
catch (Exception ex)
{
_logger.Warn(ex, "Unable to send OnMovieAdded notification to: " + notification.Definition.Name);
}
}
}
public void Handle(MovieRenamedEvent message)
{
foreach (var notification in _notificationFactory.OnRenameEnabled())
@@ -220,6 +198,7 @@ namespace NzbDrone.Core.Notifications
updateMessage.Message = $"Radarr updated from {message.PreviousVerison.ToString()} to {message.NewVersion.ToString()}";
updateMessage.PreviousVersion = message.PreviousVerison;
updateMessage.NewVersion = message.NewVersion;
updateMessage.Changes = message.Changes;
foreach (var notification in _notificationFactory.OnApplicationUpdateEnabled())
{

View File

@@ -57,15 +57,15 @@ namespace NzbDrone.Core.Notifications.Plex.Server
var partialUpdates = _partialUpdateCache.Get(settings.Host, () => PartialUpdatesAllowed(settings, version), TimeSpan.FromHours(2));
var pathScanCache = _pathScanCache.Get(settings.Host, () => PathUpdatesAllowed(settings, version), TimeSpan.FromHours(2));
var pathsUpdated = true;
var pathUpdated = true;
if (pathScanCache)
{
foreach (var movie in multipleMovies)
{
pathsUpdated &= UpdatePath(movie, sections, settings);
pathUpdated &= UpdatePath(movie, sections, settings);
if (!pathsUpdated)
if (!pathUpdated)
{
break;
}
@@ -73,7 +73,7 @@ namespace NzbDrone.Core.Notifications.Plex.Server
}
// If we couldn't path update then try partial and full update
if (!pathScanCache || (pathScanCache && !pathsUpdated))
if (!pathUpdated)
{
if (partialUpdates)
{
@@ -244,10 +244,6 @@ namespace NzbDrone.Core.Notifications.Plex.Server
pathUpdated = true;
}
else
{
_logger.Debug("Unable to update path, mapped movie path {0} is not a child of any plex libraries: {1}", mappedPath, sections.SelectMany(s => s.Locations.Select(l => l.Path)).Join(", "));
}
return pathUpdated;
}

View File

@@ -136,7 +136,9 @@ namespace NzbDrone.Core.Notifications.Webhook
EventType = WebhookEventType.ApplicationUpdate,
Message = updateMessage.Message,
PreviousVersion = updateMessage.PreviousVersion.ToString(),
NewVersion = updateMessage.NewVersion.ToString()
NewVersion = updateMessage.NewVersion.ToString(),
NewChanges = updateMessage.Changes.New,
FixedChanges = updateMessage.Changes.Fixed
};
_proxy.SendWebhook(payload, Settings);

View File

@@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookApplicationUpdatePayload : WebhookPayload
@@ -5,5 +7,7 @@ namespace NzbDrone.Core.Notifications.Webhook
public string Message { get; set; }
public string PreviousVersion { get; set; }
public string NewVersion { get; set; }
public List<string> NewChanges { get; set; }
public List<string> FixedChanges { get; set; }
}
}

View File

@@ -41,8 +41,7 @@ namespace NzbDrone.Core.Parser
new IsoLanguage("ar", "", "ara", "Arabic", Language.Arabic),
new IsoLanguage("uk", "", "ukr", "Ukrainian", Language.Ukrainian),
new IsoLanguage("fa", "", "fas", "Persian", Language.Persian),
new IsoLanguage("be", "", "ben", "Bengali", Language.Bengali),
new IsoLanguage("lt", "", "lit", "Lithuanian", Language.Lithuanian)
new IsoLanguage("be", "", "ben", "Bengali", Language.Bengali)
};
public static IsoLanguage Find(string isoCode)

View File

@@ -20,18 +20,6 @@ namespace NzbDrone.Core.Parser
private static readonly Regex[] ReportMovieTitleRegex = new[]
{
//Anime [Subgroup] and Year
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>(?![(\[]).+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(1(8|9)|20)\d{2}(?!p|i|x|\d+|\]|\W\d+)))+.*?(?<hash>\[\w{8}\])?(?:$|\.)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Anime [Subgroup] no year, versioned title, hash
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>(?![(\[]).+?)((v)(?:\d{1,2})(?:([-_. ])))(\[.*)?(?:[\[(][^])])?.*?(?<hash>\[\w{8}\])(?:$|\.)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Anime [Subgroup] no year, info in double sets of brackets, hash
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>(?![(\[]).+?)(\[.*).*?(?<hash>\[\w{8}\])(?:$|\.)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Anime [Subgroup] no year, info in parentheses or brackets, hash
new Regex(@"^(?:\[(?<subgroup>.+?)\][-_. ]?)(?<title>(?![(\[]).+)(?:[\[(][^])]).*?(?<hash>\[\w{8}\])(?:$|\.)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
//Some german or french tracker formats (missing year, ...) (Only applies to german and TrueFrench releases) - see ParserFixture for examples and tests - french removed as it broke all movies w/ french titles
new Regex(@"^(?<title>(?![(\[]).+?)((\W|_))(" + EditionRegex + @".{1,3})?(?:(?<!(19|20)\d{2}.*?)(German|TrueFrench))(.+?)(?=((19|20)\d{2}|$))(?<year>(19|20)\d{2}(?!p|i|\d+|\]|\W\d+))?(\W+|_|$)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
@@ -53,7 +41,7 @@ namespace NzbDrone.Core.Parser
new Regex(@"^(?<title>(?![(\[]).+?)?(?:(?:[-_\W](?<![)!]))*(?<year>(1(8|9)|20)\d{2}(?!p|i|\d+|\W\d+)))+(\W+|_|$)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
//As a last resort for movies that have ( or [ in their title.
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(1(8|9)|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled)
new Regex(@"^(?<title>.+?)?(?:(?:[-_\W](?<![)\[!]))*(?<year>(1(8|9)|20)\d{2}(?!p|i|\d+|\]|\W\d+)))+(\W+|_|$)(?!\\)", RegexOptions.IgnoreCase | RegexOptions.Compiled),
};
private static readonly Regex[] ReportMovieTitleFolderRegex = new[]
@@ -109,7 +97,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex ReportImdbId = new Regex(@"(?<imdbid>tt\d{7,8})", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly Regex ReportTmdbId = new Regex(@"tmdb(id)?-(?<tmdbid>\d+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private static readonly RegexReplace SimpleTitleRegex = new RegexReplace(@"(?:(480|540|576|720|1080|2160)[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*]|848x480|1280x720|1920x1080|3840x2160|4096x2160|(8|10)b(it)?|10-bit)\s*?(?![a-b0-9])",
private static readonly RegexReplace SimpleTitleRegex = new RegexReplace(@"(?:(480|540|576|720|1080|2160)[ip]|[xh][\W_]?26[45]|DD\W?5\W1|[<>?*]|848x480|1280x720|1920x1080|3840x2160|4096x2160|(8|10)b(it)?|10-bit)\s*?",
string.Empty,
RegexOptions.IgnoreCase | RegexOptions.Compiled);

View File

@@ -16,7 +16,7 @@ namespace NzbDrone.Core.Parser
private static readonly Regex SourceRegex = new Regex(@"\b(?:
(?<bluray>M?BluRay|Blu-Ray|HD.?DVD|BD(?!$)|UHDBD|UHD2BD|BDISO|BDMux|BD25|BD50|BR.?DISK)|
(?<webdl>WEB[-_. ]DL(?:mux)?|WEBDL|AmazonHD|iTunesHD|MaxdomeHD|NetflixU?HD|WebHD|[. ]WEB[. ](?:[xh][ .]?26[45]|DDP?5[. ]1)|[. ](?-i:WEB)$|(?:\d{3,4}0p)[-. ]WEB[-. ]|[-. ]WEB[-. ]\d{3,4}0p|\b\s\/\sWEB\s\/\s\b|(?:AMZN|NF|DP)[. -]WEB[. -])|
(?<webdl>WEB[-_. ]DL(?:mux)?|WEBDL|AmazonHD|iTunesHD|MaxdomeHD|NetflixU?HD|WebHD|[. ]WEB[. ](?:[xh]26[45]|DDP?5[. ]1)|[. ](?-i:WEB)$|(?:\d{3,4}0p)[-. ]WEB[-. ]|[-. ]WEB[-. ]\d{3,4}0p|\b\s\/\sWEB\s\/\s\b|(?:AMZN|NF|DP)[. -]WEB[. -])|
(?<webrip>WebRip|Web-Rip|WEBMux)|
(?<hdtv>HDTV)|
(?<bdrip>BDRip|BDLight)|
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Parser
(?<scr>SCR|SCREENER|DVDSCR|DVDSCREENER)|
(?<ts>TS[-_. ]|TELESYNC|HD-TS|HDTS|PDVD|TSRip|HDTSRip)|
(?<tc>TC|TELECINE|HD-TC|HDTC)|
(?<cam>CAMRIP|CAM|HDCAM|HQCAM|HD-CAM)|
(?<cam>CAMRIP|CAM|HDCAM|HD-CAM)|
(?<wp>WORKPRINT|WP)|
(?<pdtv>PDTV)|
(?<sdtv>SDTV)|

View File

@@ -19,7 +19,7 @@
<PackageReference Include="FluentValidation" Version="8.6.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="NLog" Version="4.7.14" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="MonoTorrent" Version="2.0.5" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />

Some files were not shown because too many files have changed in this diff Show More