mirror of
https://github.com/Radarr/Radarr.git
synced 2026-03-29 18:15:37 -04:00
Compare commits
29 Commits
v5.2.4.832
...
v5.2.6.837
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdc4aade0f | ||
|
|
b2300dbf41 | ||
|
|
44289d30f9 | ||
|
|
260fb88f85 | ||
|
|
119cdf6f09 | ||
|
|
c8d30fd214 | ||
|
|
7e9e528d3b | ||
|
|
8554c0d9cb | ||
|
|
22cc34b4fe | ||
|
|
990785ebfc | ||
|
|
957be99401 | ||
|
|
4bcde25e29 | ||
|
|
1d70f36e7d | ||
|
|
cc0a448bc8 | ||
|
|
c9e977baea | ||
|
|
6cb9a46cd4 | ||
|
|
eef379277a | ||
|
|
41fef47684 | ||
|
|
fcda6faf3d | ||
|
|
79bbf9c50b | ||
|
|
43d2f2804b | ||
|
|
fa62f3f66a | ||
|
|
229d91fe40 | ||
|
|
2673d1eee4 | ||
|
|
e59fd1118f | ||
|
|
c1fd33b152 | ||
|
|
2f58c8676f | ||
|
|
defc448304 | ||
|
|
3ec3358728 |
@@ -9,13 +9,13 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '5.2.4'
|
||||
majorVersion: '5.2.6'
|
||||
minorVersion: $[counter('minorVersion', 2000)]
|
||||
radarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
|
||||
sentryOrg: 'servarr'
|
||||
sentryUrl: 'https://sentry.servarr.com'
|
||||
dotnetVersion: '6.0.413'
|
||||
dotnetVersion: '6.0.417'
|
||||
nodeVersion: '16.X'
|
||||
innoVersion: '6.2.0'
|
||||
windowsImage: 'windows-2022'
|
||||
|
||||
@@ -85,8 +85,13 @@
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.studio,
|
||||
.genres {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.links {
|
||||
margin-left: 8px;
|
||||
margin-left: 5px;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ interface CssExports {
|
||||
'certification': string;
|
||||
'content': string;
|
||||
'exclusionIcon': string;
|
||||
'genres': string;
|
||||
'icons': string;
|
||||
'links': string;
|
||||
'overlay': string;
|
||||
@@ -14,6 +15,7 @@ interface CssExports {
|
||||
'runtime': string;
|
||||
'searchResult': string;
|
||||
'statusContainer': string;
|
||||
'studio': string;
|
||||
'title': string;
|
||||
'titleContainer': string;
|
||||
'titleRow': string;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import ImdbRating from 'Components/ImdbRating';
|
||||
import Label from 'Components/Label';
|
||||
import Link from 'Components/Link/Link';
|
||||
import TmdbRating from 'Components/TmdbRating';
|
||||
@@ -61,6 +62,7 @@ class AddNewMovieSearchResult extends Component {
|
||||
titleSlug,
|
||||
year,
|
||||
studio,
|
||||
genres,
|
||||
status,
|
||||
overview,
|
||||
ratings,
|
||||
@@ -76,6 +78,7 @@ class AddNewMovieSearchResult extends Component {
|
||||
hasFile,
|
||||
isAvailable,
|
||||
movieFile,
|
||||
queueItem,
|
||||
runtime,
|
||||
movieRuntimeFormat,
|
||||
certification
|
||||
@@ -197,13 +200,46 @@ class AddNewMovieSearchResult extends Component {
|
||||
/>
|
||||
</Label>
|
||||
|
||||
{
|
||||
ratings.imdb ?
|
||||
<Label size={sizes.LARGE}>
|
||||
<ImdbRating
|
||||
ratings={ratings}
|
||||
iconSize={13}
|
||||
/>
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!!studio &&
|
||||
<Label size={sizes.LARGE}>
|
||||
{studio}
|
||||
<Icon
|
||||
name={icons.STUDIO}
|
||||
size={13}
|
||||
/>
|
||||
|
||||
<span className={styles.studio}>
|
||||
{studio}
|
||||
</span>
|
||||
</Label>
|
||||
}
|
||||
|
||||
{
|
||||
genres.length > 0 ?
|
||||
<Label size={sizes.LARGE}>
|
||||
<Icon
|
||||
name={icons.GENRE}
|
||||
size={13}
|
||||
/>
|
||||
|
||||
<span className={styles.genres}>
|
||||
{genres.slice(0, 3).join(', ')}
|
||||
</span>
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
<Tooltip
|
||||
anchor={
|
||||
<Label
|
||||
@@ -215,15 +251,15 @@ class AddNewMovieSearchResult extends Component {
|
||||
/>
|
||||
|
||||
<span className={styles.links}>
|
||||
Links
|
||||
{translate('Links')}
|
||||
</span>
|
||||
</Label>
|
||||
}
|
||||
tooltip={
|
||||
<MovieDetailsLinks
|
||||
tmdbId={tmdbId}
|
||||
youTubeTrailerId={youTubeTrailerId}
|
||||
imdbId={imdbId}
|
||||
youTubeTrailerId={youTubeTrailerId}
|
||||
/>
|
||||
}
|
||||
canFlip={true}
|
||||
@@ -237,6 +273,7 @@ class AddNewMovieSearchResult extends Component {
|
||||
hasMovieFiles={hasFile}
|
||||
monitored={monitored}
|
||||
isAvailable={isAvailable}
|
||||
queueItem={queueItem}
|
||||
id={id}
|
||||
useLabel={true}
|
||||
colorImpairedMode={colorImpairedMode}
|
||||
@@ -273,6 +310,7 @@ AddNewMovieSearchResult.propTypes = {
|
||||
titleSlug: PropTypes.string.isRequired,
|
||||
year: PropTypes.number.isRequired,
|
||||
studio: PropTypes.string,
|
||||
genres: PropTypes.arrayOf(PropTypes.string),
|
||||
status: PropTypes.string.isRequired,
|
||||
overview: PropTypes.string,
|
||||
ratings: PropTypes.object.isRequired,
|
||||
@@ -283,15 +321,19 @@ AddNewMovieSearchResult.propTypes = {
|
||||
isExclusionMovie: PropTypes.bool.isRequired,
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
id: PropTypes.number,
|
||||
queueItems: PropTypes.arrayOf(PropTypes.object),
|
||||
monitored: PropTypes.bool.isRequired,
|
||||
hasFile: PropTypes.bool.isRequired,
|
||||
isAvailable: PropTypes.bool.isRequired,
|
||||
movieFile: PropTypes.object,
|
||||
queueItem: PropTypes.object,
|
||||
colorImpairedMode: PropTypes.bool,
|
||||
runtime: PropTypes.number.isRequired,
|
||||
movieRuntimeFormat: PropTypes.string.isRequired,
|
||||
certification: PropTypes.string
|
||||
};
|
||||
|
||||
AddNewMovieSearchResult.defaultProps = {
|
||||
genres: []
|
||||
};
|
||||
|
||||
export default AddNewMovieSearchResult;
|
||||
|
||||
@@ -10,14 +10,18 @@ function createMapStateToProps() {
|
||||
createExistingMovieSelector(),
|
||||
createExclusionMovieSelector(),
|
||||
createDimensionsSelector(),
|
||||
(state) => state.queue.details.items,
|
||||
(state, { internalId }) => internalId,
|
||||
(state) => state.settings.ui.item.movieRuntimeFormat,
|
||||
(isExistingMovie, isExclusionMovie, dimensions, internalId, movieRuntimeFormat) => {
|
||||
(isExistingMovie, isExclusionMovie, dimensions, queueItems, internalId, movieRuntimeFormat) => {
|
||||
const queueItem = queueItems.find((item) => internalId > 0 && item.movieId === internalId);
|
||||
|
||||
return {
|
||||
existingMovieId: internalId,
|
||||
isExistingMovie,
|
||||
isExclusionMovie,
|
||||
isSmallScreen: dimensions.isSmallScreen,
|
||||
queueItem,
|
||||
movieRuntimeFormat
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
.contentContainer {
|
||||
z-index: $popperZIndex;
|
||||
margin-top: 4px;
|
||||
/* 400px container witdh with 8px padding on each side */
|
||||
/* 400px container width with 8px padding on each side */
|
||||
width: 384px;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ class CalendarConnector extends Component {
|
||||
gotoCalendarToday
|
||||
} = this.props;
|
||||
|
||||
registerPagePopulator(this.repopulate);
|
||||
registerPagePopulator(this.repopulate, ['movieFileUpdated', 'movieFileDeleted']);
|
||||
|
||||
if (useCurrentPage) {
|
||||
fetchCalendar();
|
||||
|
||||
@@ -167,7 +167,7 @@ class SignalRConnector extends Component {
|
||||
const resource = body.resource;
|
||||
const status = resource.status;
|
||||
|
||||
// Both sucessful and failed commands need to be
|
||||
// Both successful and failed commands need to be
|
||||
// completed, otherwise they spin until they timeout.
|
||||
|
||||
if (status === 'completed' || status === 'failed') {
|
||||
@@ -187,6 +187,8 @@ class SignalRConnector extends Component {
|
||||
repopulatePage('movieFileUpdated');
|
||||
} else if (body.action === 'deleted') {
|
||||
this.props.dispatchRemoveItem({ section, id: body.resource.id });
|
||||
|
||||
repopulatePage('movieFileDeleted');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
"start_url": "../../../../",
|
||||
"theme_color": "#3a3f51",
|
||||
"background_color": "#3a3f51",
|
||||
"display": "standalone"
|
||||
"display": "minimal-ui"
|
||||
}
|
||||
|
||||
@@ -6,31 +6,43 @@ import MovieTitlesTableContent from './MovieTitlesTableContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { movieId }) => movieId,
|
||||
(state) => state.movies,
|
||||
(movies) => {
|
||||
return movies;
|
||||
(movieId, movies) => {
|
||||
const {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
items
|
||||
} = movies;
|
||||
|
||||
const alternateTitles = items.find((m) => m.id === movieId)?.alternateTitles;
|
||||
|
||||
return {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
alternateTitles
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
// fetchMovies
|
||||
};
|
||||
|
||||
class MovieTitlesTableContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const movie = this.props.items.filter((obj) => {
|
||||
return obj.id === this.props.movieId;
|
||||
});
|
||||
const {
|
||||
alternateTitles,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<MovieTitlesTableContent
|
||||
{...this.props}
|
||||
items={movie[0].alternateTitles}
|
||||
{...otherProps}
|
||||
items={alternateTitles}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -38,7 +50,11 @@ class MovieTitlesTableContentConnector extends Component {
|
||||
|
||||
MovieTitlesTableContentConnector.propTypes = {
|
||||
movieId: PropTypes.number.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, mapDispatchToProps)(MovieTitlesTableContentConnector);
|
||||
MovieTitlesTableContentConnector.defaultProps = {
|
||||
alternateTitles: []
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps)(MovieTitlesTableContentConnector);
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './RootFolderRow.css';
|
||||
|
||||
function RootFolderRow(props) {
|
||||
const {
|
||||
id,
|
||||
path,
|
||||
accessible,
|
||||
freeSpace,
|
||||
unmappedFolders,
|
||||
onDeletePress
|
||||
} = props;
|
||||
|
||||
const isUnavailable = !accessible;
|
||||
|
||||
return (
|
||||
<TableRow>
|
||||
<TableRowCell>
|
||||
{
|
||||
isUnavailable ?
|
||||
<div className={styles.unavailablePath}>
|
||||
{path}
|
||||
|
||||
<Label
|
||||
className={styles.unavailableLabel}
|
||||
kind={kinds.DANGER}
|
||||
>
|
||||
{translate('Unavailable')}
|
||||
</Label>
|
||||
</div> :
|
||||
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`/add/import/${id}`}
|
||||
>
|
||||
{path}
|
||||
</Link>
|
||||
}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.freeSpace}>
|
||||
{(isUnavailable || isNaN(freeSpace)) ? '-' : formatBytes(freeSpace)}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.unmappedFolders}>
|
||||
{isUnavailable ? '-' : unmappedFolders.length}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
<IconButton
|
||||
title={translate('RemoveRootFolder')}
|
||||
name={icons.REMOVE}
|
||||
onPress={onDeletePress}
|
||||
/>
|
||||
</TableRowCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
RootFolderRow.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
accessible: PropTypes.bool.isRequired,
|
||||
freeSpace: PropTypes.number,
|
||||
unmappedFolders: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onDeletePress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
RootFolderRow.defaultProps = {
|
||||
unmappedFolders: []
|
||||
};
|
||||
|
||||
export default RootFolderRow;
|
||||
@@ -1,92 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import RootFolderRowConnector from './RootFolderRowConnector';
|
||||
|
||||
const rootFolderColumns = [
|
||||
{
|
||||
name: 'path',
|
||||
get label() {
|
||||
return translate('Path');
|
||||
},
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'freeSpace',
|
||||
get label() {
|
||||
return translate('FreeSpace');
|
||||
},
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'unmappedFolders',
|
||||
get label() {
|
||||
return translate('UnmappedFolders');
|
||||
},
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'actions',
|
||||
isVisible: true
|
||||
}
|
||||
];
|
||||
|
||||
function RootFolders(props) {
|
||||
const {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error,
|
||||
items
|
||||
} = props;
|
||||
|
||||
if (isFetching && !isPopulated) {
|
||||
return (
|
||||
<LoadingIndicator />
|
||||
);
|
||||
}
|
||||
|
||||
if (!isFetching && !!error) {
|
||||
return (
|
||||
<Alert kind={kinds.DANGER}>
|
||||
{translate('UnableToLoadRootFolders')}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={rootFolderColumns}
|
||||
>
|
||||
<TableBody>
|
||||
{
|
||||
items.map((rootFolder) => {
|
||||
return (
|
||||
<RootFolderRowConnector
|
||||
key={rootFolder.id}
|
||||
id={rootFolder.id}
|
||||
path={rootFolder.path}
|
||||
accessible={rootFolder.accessible}
|
||||
freeSpace={rootFolder.freeSpace}
|
||||
unmappedFolders={rootFolder.unmappedFolders}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
RootFolders.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default RootFolders;
|
||||
@@ -1,72 +0,0 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal';
|
||||
import Icon from 'Components/Icon';
|
||||
import Button from 'Components/Link/Button';
|
||||
import { icons, kinds, sizes } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './AddRootFolder.css';
|
||||
|
||||
class AddRootFolder extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
isAddNewRootFolderModalOpen: false
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
|
||||
onAddNewRootFolderPress = () => {
|
||||
this.setState({ isAddNewRootFolderModalOpen: true });
|
||||
};
|
||||
|
||||
onNewRootFolderSelect = ({ value }) => {
|
||||
this.props.onNewRootFolderSelect(value);
|
||||
};
|
||||
|
||||
onAddRootFolderModalClose = () => {
|
||||
this.setState({ isAddNewRootFolderModalOpen: false });
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.addRootFolderButtonContainer}>
|
||||
<Button
|
||||
kind={kinds.PRIMARY}
|
||||
size={sizes.LARGE}
|
||||
onPress={this.onAddNewRootFolderPress}
|
||||
>
|
||||
<Icon
|
||||
className={styles.importButtonIcon}
|
||||
name={icons.DRIVE}
|
||||
/>
|
||||
{translate('AddRootFolder')}
|
||||
</Button>
|
||||
|
||||
<FileBrowserModal
|
||||
isOpen={this.state.isAddNewRootFolderModalOpen}
|
||||
name="rootFolderPath"
|
||||
value=""
|
||||
onChange={this.onNewRootFolderSelect}
|
||||
onModalClose={this.onAddRootFolderModalClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddRootFolder.propTypes = {
|
||||
onNewRootFolderSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default AddRootFolder;
|
||||
@@ -130,7 +130,10 @@ export const actionHandlers = handleThunks({
|
||||
|
||||
promise.done((data) => {
|
||||
const updatedItem = _.cloneDeep(data);
|
||||
updatedItem.internalId = updatedItem.id;
|
||||
updatedItem.id = updatedItem.tmdbId;
|
||||
delete updatedItem.images;
|
||||
|
||||
const actions = [
|
||||
updateItem({ section: 'movies', ...data }),
|
||||
updateItem({ section: 'addMovie', ...updatedItem }),
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@fortawesome/react-fontawesome": "0.2.0",
|
||||
"@juggle/resize-observer": "3.4.0",
|
||||
"@microsoft/signalr": "6.0.21",
|
||||
"@microsoft/signalr": "6.0.25",
|
||||
"@sentry/browser": "7.51.2",
|
||||
"@sentry/integrations": "7.51.2",
|
||||
"@types/node": "18.16.8",
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace NzbDrone.Common.Test.Http
|
||||
// Use mirrors for tests that use two hosts
|
||||
var candidates = new[] { "httpbin1.servarr.com" };
|
||||
|
||||
// httpbin.org is broken right now, occassionally redirecting to https if it's unavailable.
|
||||
// httpbin.org is broken right now, occasionally redirecting to https if it's unavailable.
|
||||
_httpBinHost = mainHost;
|
||||
_httpBinHosts = candidates.Where(IsTestSiteAvailable).ToArray();
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Coudn't set app folder permission");
|
||||
_logger.Warn(ex, "Couldn't set app folder permission");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry
|
||||
_debounce = new SentryDebounce();
|
||||
|
||||
// initialize to true and reconfigure later
|
||||
// Otherwise it will default to false and any errors occuring
|
||||
// Otherwise it will default to false and any errors occurring
|
||||
// before config file gets read will not be filtered
|
||||
FilterEvents = true;
|
||||
SentryEnabled = true;
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace NzbDrone.Common.OAuth
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a request elements concatentation value to send with a request.
|
||||
/// Creates a request elements concatenation value to send with a request.
|
||||
/// This is also known as the signature base.
|
||||
/// </summary>
|
||||
/// <seealso href="http://oauth.net/core/1.0#rfc.section.9.1.3"/>
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<DefineConstants Condition="'$(RuntimeIdentifier)' == 'linux-musl-x64' or '$(RuntimeIdentifier)' == 'linux-musl-arm64'">ISMUSL</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.1" />
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.3" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.3" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.4" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.6" />
|
||||
<PackageReference Include="Sentry" Version="3.23.1" />
|
||||
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.3.3" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.8" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.9" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace NzbDrone.Common
|
||||
|
||||
if (dacls.Contains(authenticatedUsersDacl))
|
||||
{
|
||||
// Permssions already set
|
||||
// Permissions already set
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using NUnit.Framework;
|
||||
using NzbDrone.Core.Housekeeping.Housekeepers;
|
||||
using NzbDrone.Core.ImportLists;
|
||||
using NzbDrone.Core.ImportLists.ImportListMovies;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
@@ -42,8 +43,13 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
{
|
||||
GivenImportList();
|
||||
|
||||
var movieMetadata = Builder<MovieMetadata>.CreateNew().BuildNew();
|
||||
|
||||
Db.Insert(movieMetadata);
|
||||
|
||||
var status = Builder<ImportListMovie>.CreateNew()
|
||||
.With(h => h.ListId = _importList.Id)
|
||||
.With(b => b.MovieMetadataId = movieMetadata.Id)
|
||||
.BuildNew();
|
||||
Db.Insert(status);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
|
||||
[TestCase(HdrFormat.Hdr10Plus, "HDR10Plus")]
|
||||
[TestCase(HdrFormat.DolbyVision, "DV")]
|
||||
[TestCase(HdrFormat.DolbyVisionHdr10, "DV HDR10")]
|
||||
[TestCase(HdrFormat.DolbyVisionHdr10Plus, "DV HDR10Plus")]
|
||||
[TestCase(HdrFormat.DolbyVisionHlg, "DV HLG")]
|
||||
[TestCase(HdrFormat.DolbyVisionSdr, "DV SDR")]
|
||||
public void should_format_video_dynamic_range_type(HdrFormat format, string expectedVideoDynamicRangeType)
|
||||
|
||||
@@ -116,6 +116,8 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.HdrDynamicMetadataSpmte2094", null, HdrFormat.Hdr10Plus)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", null, HdrFormat.DolbyVision)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", 1, HdrFormat.DolbyVisionHdr10)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData,FFMpegCore.HdrDynamicMetadataSpmte2094", 1, HdrFormat.DolbyVisionHdr10Plus)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData,FFMpegCore.HdrDynamicMetadataSpmte2094", 6, HdrFormat.DolbyVisionHdr10Plus)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", 2, HdrFormat.DolbyVisionSdr)]
|
||||
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", 4, HdrFormat.DolbyVisionHlg)]
|
||||
public void should_detect_hdr_correctly(int bitDepth, string colourPrimaries, string transferFunction, string sideDataTypes, int? doviConfigId, HdrFormat expected)
|
||||
|
||||
@@ -48,13 +48,14 @@ namespace NzbDrone.Core.Test.NotificationTests
|
||||
Subject.Definition = _traktDefinition;
|
||||
}
|
||||
|
||||
private void GiventValidMediaInfo(Quality quality, string audioChannels, string audioFormat, string scanType)
|
||||
private void GiventValidMediaInfo(Quality quality, string audioChannels, string audioFormat, string scanType, HdrFormat hdrFormat = HdrFormat.None)
|
||||
{
|
||||
_downloadMessage.MovieFile.MediaInfo = new MediaInfoModel
|
||||
{
|
||||
AudioChannelPositions = audioChannels,
|
||||
AudioFormat = audioFormat,
|
||||
ScanType = scanType
|
||||
ScanType = scanType,
|
||||
VideoHdrFormat = hdrFormat
|
||||
};
|
||||
|
||||
_downloadMessage.MovieFile.Quality.Quality = quality;
|
||||
@@ -72,7 +73,7 @@ namespace NzbDrone.Core.Test.NotificationTests
|
||||
[Test]
|
||||
public void should_add_collection_movie_if_valid_mediainfo()
|
||||
{
|
||||
GiventValidMediaInfo(Quality.Bluray1080p, "5.1", "DTS", "Progressive");
|
||||
GiventValidMediaInfo(Quality.Bluray2160p, "5.1", "DTS", "Progressive", HdrFormat.DolbyVisionHdr10);
|
||||
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
|
||||
@@ -80,15 +81,16 @@ namespace NzbDrone.Core.Test.NotificationTests
|
||||
.Verify(v => v.AddToCollection(It.Is<TraktCollectMoviesResource>(t =>
|
||||
t.Movies.First().Audio == "dts" &&
|
||||
t.Movies.First().AudioChannels == "5.1" &&
|
||||
t.Movies.First().Resolution == "hd_1080p" &&
|
||||
t.Movies.First().MediaType == "bluray"),
|
||||
t.Movies.First().Resolution == "uhd_4k" &&
|
||||
t.Movies.First().MediaType == "bluray" &&
|
||||
t.Movies.First().Hdr == "hdr10"),
|
||||
It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_format_audio_channels_to_one_decimal_when_adding_collection_movie()
|
||||
{
|
||||
GiventValidMediaInfo(Quality.Bluray1080p, "2.0", "DTS", "Progressive");
|
||||
GiventValidMediaInfo(Quality.Bluray2160p, "2.0", "DTS", "Progressive", HdrFormat.DolbyVisionHdr10);
|
||||
|
||||
Subject.OnDownload(_downloadMessage);
|
||||
|
||||
@@ -96,8 +98,9 @@ namespace NzbDrone.Core.Test.NotificationTests
|
||||
.Verify(v => v.AddToCollection(It.Is<TraktCollectMoviesResource>(t =>
|
||||
t.Movies.First().Audio == "dts" &&
|
||||
t.Movies.First().AudioChannels == "2.0" &&
|
||||
t.Movies.First().Resolution == "hd_1080p" &&
|
||||
t.Movies.First().MediaType == "bluray"),
|
||||
t.Movies.First().Resolution == "uhd_4k" &&
|
||||
t.Movies.First().MediaType == "bluray" &&
|
||||
t.Movies.First().Hdr == "hdr10"),
|
||||
It.IsAny<string>()), Times.Once());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public interface IConnectionStringFactory
|
||||
{
|
||||
string MainDbConnectionString { get; }
|
||||
string LogDbConnectionString { get; }
|
||||
DatabaseConnectionInfo MainDbConnection { get; }
|
||||
DatabaseConnectionInfo LogDbConnection { get; }
|
||||
string GetDatabasePath(string connectionString);
|
||||
}
|
||||
|
||||
@@ -22,15 +22,15 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
_configFileProvider = configFileProvider;
|
||||
|
||||
MainDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
|
||||
MainDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresMainDb) :
|
||||
GetConnectionString(appFolderInfo.GetDatabase());
|
||||
|
||||
LogDbConnectionString = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
|
||||
LogDbConnection = _configFileProvider.PostgresHost.IsNotNullOrWhiteSpace() ? GetPostgresConnectionString(_configFileProvider.PostgresLogDb) :
|
||||
GetConnectionString(appFolderInfo.GetLogDatabase());
|
||||
}
|
||||
|
||||
public string MainDbConnectionString { get; private set; }
|
||||
public string LogDbConnectionString { get; private set; }
|
||||
public DatabaseConnectionInfo MainDbConnection { get; private set; }
|
||||
public DatabaseConnectionInfo LogDbConnection { get; private set; }
|
||||
|
||||
public string GetDatabasePath(string connectionString)
|
||||
{
|
||||
@@ -39,7 +39,7 @@ namespace NzbDrone.Core.Datastore
|
||||
return connectionBuilder.DataSource;
|
||||
}
|
||||
|
||||
private static string GetConnectionString(string dbPath)
|
||||
private static DatabaseConnectionInfo GetConnectionString(string dbPath)
|
||||
{
|
||||
var connectionBuilder = new SQLiteConnectionStringBuilder
|
||||
{
|
||||
@@ -57,21 +57,22 @@ namespace NzbDrone.Core.Datastore
|
||||
connectionBuilder.Add("Full FSync", true);
|
||||
}
|
||||
|
||||
return connectionBuilder.ConnectionString;
|
||||
return new DatabaseConnectionInfo(DatabaseType.SQLite, connectionBuilder.ConnectionString);
|
||||
}
|
||||
|
||||
private string GetPostgresConnectionString(string dbName)
|
||||
private DatabaseConnectionInfo GetPostgresConnectionString(string dbName)
|
||||
{
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder();
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder
|
||||
{
|
||||
Database = dbName,
|
||||
Host = _configFileProvider.PostgresHost,
|
||||
Username = _configFileProvider.PostgresUser,
|
||||
Password = _configFileProvider.PostgresPassword,
|
||||
Port = _configFileProvider.PostgresPort,
|
||||
Enlist = false
|
||||
};
|
||||
|
||||
connectionBuilder.Database = dbName;
|
||||
connectionBuilder.Host = _configFileProvider.PostgresHost;
|
||||
connectionBuilder.Username = _configFileProvider.PostgresUser;
|
||||
connectionBuilder.Password = _configFileProvider.PostgresPassword;
|
||||
connectionBuilder.Port = _configFileProvider.PostgresPort;
|
||||
connectionBuilder.Enlist = false;
|
||||
|
||||
return connectionBuilder.ConnectionString;
|
||||
return new DatabaseConnectionInfo(DatabaseType.PostgreSQL, connectionBuilder.ConnectionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
src/NzbDrone.Core/Datastore/DatabaseConnectionInfo.cs
Normal file
14
src/NzbDrone.Core/Datastore/DatabaseConnectionInfo.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class DatabaseConnectionInfo
|
||||
{
|
||||
public DatabaseConnectionInfo(DatabaseType databaseType, string connectionString)
|
||||
{
|
||||
DatabaseType = databaseType;
|
||||
ConnectionString = connectionString;
|
||||
}
|
||||
|
||||
public DatabaseType DatabaseType { get; internal set; }
|
||||
public string ConnectionString { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Data.Common;
|
||||
using System.Data.SQLite;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
using Npgsql;
|
||||
using NzbDrone.Common.Disk;
|
||||
@@ -60,22 +61,22 @@ namespace NzbDrone.Core.Datastore
|
||||
|
||||
public IDatabase Create(MigrationContext migrationContext)
|
||||
{
|
||||
string connectionString;
|
||||
DatabaseConnectionInfo connectionInfo;
|
||||
|
||||
switch (migrationContext.MigrationType)
|
||||
{
|
||||
case MigrationType.Main:
|
||||
{
|
||||
connectionString = _connectionStringFactory.MainDbConnectionString;
|
||||
CreateMain(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.MainDbConnection;
|
||||
CreateMain(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MigrationType.Log:
|
||||
{
|
||||
connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||
CreateLog(connectionString, migrationContext);
|
||||
connectionInfo = _connectionStringFactory.LogDbConnection;
|
||||
CreateLog(connectionInfo.ConnectionString, migrationContext, connectionInfo.DatabaseType);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -90,14 +91,14 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
DbConnection conn;
|
||||
|
||||
if (connectionString.Contains(".db"))
|
||||
if (connectionInfo.DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
conn = SQLiteFactory.Instance.CreateConnection();
|
||||
conn.ConnectionString = connectionString;
|
||||
conn.ConnectionString = connectionInfo.ConnectionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn = new NpgsqlConnection(connectionString);
|
||||
conn = new NpgsqlConnection(connectionInfo.ConnectionString);
|
||||
}
|
||||
|
||||
conn.Open();
|
||||
@@ -107,12 +108,12 @@ namespace NzbDrone.Core.Datastore
|
||||
return db;
|
||||
}
|
||||
|
||||
private void CreateMain(string connectionString, MigrationContext migrationContext)
|
||||
private void CreateMain(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_restoreDatabaseService.Restore();
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
@@ -135,15 +136,17 @@ namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
Logger.Error(e, "Failure to connect to Postgres DB, {0} retries remaining", retryCount);
|
||||
|
||||
Thread.Sleep(5000);
|
||||
|
||||
try
|
||||
{
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (--retryCount > 0)
|
||||
{
|
||||
System.Threading.Thread.Sleep(5000);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -162,11 +165,11 @@ namespace NzbDrone.Core.Datastore
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLog(string connectionString, MigrationContext migrationContext)
|
||||
private void CreateLog(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
try
|
||||
{
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (SQLiteException e)
|
||||
{
|
||||
@@ -186,7 +189,7 @@ namespace NzbDrone.Core.Datastore
|
||||
Logger.Error("Unable to recreate logging database automatically. It will need to be removed manually.");
|
||||
}
|
||||
|
||||
_migrationController.Migrate(connectionString, migrationContext);
|
||||
_migrationController.Migrate(connectionString, migrationContext, databaseType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace NzbDrone.Core.Datastore
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits the memeber access expression. To be implemented by user.
|
||||
/// Visits the member access expression. To be implemented by user.
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
{
|
||||
public interface IMigrationController
|
||||
{
|
||||
void Migrate(string connectionString, MigrationContext migrationContext);
|
||||
void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType);
|
||||
}
|
||||
|
||||
public class MigrationController : IMigrationController
|
||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
_migrationLoggerProvider = migrationLoggerProvider;
|
||||
}
|
||||
|
||||
public void Migrate(string connectionString, MigrationContext migrationContext)
|
||||
public void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||
|
||||
ServiceProvider serviceProvider;
|
||||
|
||||
var db = connectionString.Contains(".db") ? "sqlite" : "postgres";
|
||||
var db = databaseType == DatabaseType.SQLite ? "sqlite" : "postgres";
|
||||
|
||||
serviceProvider = new ServiceCollection()
|
||||
.AddLogging(b => b.AddNLog())
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
private int ComparePeersIfTorrent(DownloadDecision x, DownloadDecision y)
|
||||
{
|
||||
// Different protocols should get caught when checking the preferred protocol,
|
||||
// since we're dealing with the same movie in our comparisions
|
||||
// since we're dealing with the same movie in our comparisons
|
||||
if (x.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Torrent ||
|
||||
y.RemoteMovie.Release.DownloadProtocol != DownloadProtocol.Torrent)
|
||||
{
|
||||
|
||||
@@ -78,7 +78,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
return false;
|
||||
}
|
||||
|
||||
_logger.Debug("New item has a better custom format score");
|
||||
_logger.Debug("New item's custom formats [{0}] ({1}) improve on [{2}] ({3}), accepting",
|
||||
newCustomFormats.ConcatToString(),
|
||||
newFormatScore,
|
||||
currentCustomFormats.ConcatToString(),
|
||||
currentFormatScore);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace NzbDrone.Core.Download.Clients.Flood
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result.Where(t => t.IsNotNullOrWhiteSpace());
|
||||
}
|
||||
|
||||
public override string Name => "Flood";
|
||||
|
||||
@@ -141,7 +141,8 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
||||
|
||||
private TransmissionResponse GetSessionVariables(TransmissionSettings settings)
|
||||
{
|
||||
// Retrieve transmission information such as the default download directory, bandwith throttling and seed ratio.
|
||||
// Retrieve transmission information such as the default download directory, bandwidth throttling and seed ratio.
|
||||
|
||||
return ProcessRequest("session-get", null, settings);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ namespace NzbDrone.Core.Extras.Metadata
|
||||
|
||||
foreach (var possibleMetadataFile in filterResult.FilesOnDisk)
|
||||
{
|
||||
// Don't process files that have known Subtitle file extensions (saves a bit of unecessary processing)
|
||||
// Don't process files that have known Subtitle file extensions (saves a bit of unnecessary processing)
|
||||
|
||||
if (SubtitleFileExtensions.Extensions.Contains(Path.GetExtension(possibleMetadataFile)))
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -13,15 +13,33 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
CleanupOrphanedByImportLists();
|
||||
CleanupOrphanedByMovieMetadata();
|
||||
}
|
||||
|
||||
private void CleanupOrphanedByImportLists()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
|
||||
mapper.Execute(@"DELETE FROM ""ImportListMovies""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ImportListMovies"".""Id"" FROM ""ImportListMovies""
|
||||
LEFT OUTER JOIN ""ImportLists""
|
||||
ON ""ImportListMovies"".""ListId"" = ""ImportLists"".""Id""
|
||||
WHERE ""ImportLists"".""Id"" IS NULL)");
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ImportListMovies"".""Id""
|
||||
FROM ""ImportListMovies""
|
||||
LEFT OUTER JOIN ""ImportLists"" ON ""ImportListMovies"".""ListId"" = ""ImportLists"".""Id""
|
||||
WHERE ""ImportLists"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void CleanupOrphanedByMovieMetadata()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
|
||||
mapper.Execute(@"DELETE FROM ""ImportListMovies""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ImportListMovies"".""Id""
|
||||
FROM ""ImportListMovies""
|
||||
LEFT OUTER JOIN ""MovieMetadata"" ON ""ImportListMovies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
|
||||
WHERE ""MovieMetadata"".""Id"" IS NULL)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace NzbDrone.Core.ImportLists
|
||||
|
||||
if (excludedMovie != null)
|
||||
{
|
||||
_logger.Debug("{0} [{1}] Rejected due to list exlcusion", report.TmdbId, report.Title);
|
||||
_logger.Debug("{0} [{1}] Rejected due to list exclusion", report.TmdbId, report.Title);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,13 +48,11 @@ namespace NzbDrone.Core.Indexers.Newznab
|
||||
{
|
||||
yield return GetDefinition("DOGnzb", GetSettings("https://api.dognzb.cr"));
|
||||
yield return GetDefinition("DrunkenSlug", GetSettings("https://drunkenslug.com"));
|
||||
yield return GetDefinition("Nzb-Tortuga", GetSettings("https://www.nzb-tortuga.com"));
|
||||
yield return GetDefinition("Nzb.su", GetSettings("https://api.nzb.su"));
|
||||
yield return GetDefinition("NZBCat", GetSettings("https://nzb.cat"));
|
||||
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws", categories: new[] { 2030, 2040, 2045, 2050, 2060, 2070, 2080, 2090 }));
|
||||
yield return GetDefinition("NZBFinder.ws", GetSettings("https://nzbfinder.ws", categories: new[] { 2030, 2040, 2045, 2050, 2060, 2070 }));
|
||||
yield return GetDefinition("NZBgeek", GetSettings("https://api.nzbgeek.info"));
|
||||
yield return GetDefinition("nzbplanet.net", GetSettings("https://api.nzbplanet.net"));
|
||||
yield return GetDefinition("OZnzb.com", GetSettings("https://api.oznzb.com"));
|
||||
yield return GetDefinition("SimplyNZBs", GetSettings("https://simplynzbs.com"));
|
||||
yield return GetDefinition("Tabula Rasa", GetSettings("https://www.tabula-rasa.pw", apiPath: @"/api/v1/api"));
|
||||
yield return GetDefinition("Usenet Crawler", GetSettings("https://www.usenet-crawler.com"));
|
||||
|
||||
@@ -91,6 +91,10 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
||||
Scene = torrent.Scene,
|
||||
Approved = torrent.Checked,
|
||||
ImdbId = result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0,
|
||||
Source = torrent.Source,
|
||||
Container = torrent.Container,
|
||||
Codec = torrent.Codec,
|
||||
Resolution = torrent.Resolution,
|
||||
IndexerFlags = flags
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,16 +88,15 @@ namespace NzbDrone.Core.Instrumentation
|
||||
|
||||
log.Level = logEvent.Level.Name;
|
||||
|
||||
var connectionString = _connectionStringFactory.LogDbConnectionString;
|
||||
var connectionInfo = _connectionStringFactory.LogDbConnection;
|
||||
|
||||
// TODO: Probably need more robust way to differentiate what's being used
|
||||
if (connectionString.Contains(".db"))
|
||||
if (connectionInfo.DatabaseType == DatabaseType.SQLite)
|
||||
{
|
||||
WriteSqliteLog(log, connectionString);
|
||||
WriteSqliteLog(log, connectionInfo.ConnectionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
WritePostgresLog(log, connectionString);
|
||||
WritePostgresLog(log, connectionInfo.ConnectionString);
|
||||
}
|
||||
}
|
||||
catch (NpgsqlException ex)
|
||||
@@ -136,8 +135,10 @@ namespace NzbDrone.Core.Instrumentation
|
||||
private void WriteSqliteLog(Log log, string connectionString)
|
||||
{
|
||||
using (var connection =
|
||||
new SQLiteConnection(connectionString).OpenAndReturn())
|
||||
SQLiteFactory.Instance.CreateConnection())
|
||||
{
|
||||
connection.ConnectionString = connectionString;
|
||||
connection.Open();
|
||||
using (var sqlCommand = connection.CreateCommand())
|
||||
{
|
||||
sqlCommand.CommandText = INSERT_COMMAND;
|
||||
|
||||
@@ -301,7 +301,7 @@
|
||||
"UsenetDelayHelpText": "Verzögerung in Minuten before ein Usenet-Release erfasst wird",
|
||||
"WhitelistedHardcodedSubsHelpText": "Hier gesetzte Untertitel Tags werden nciht als hartcodiert erachtet",
|
||||
"EnableAutoHelpText": "Wenn aktiviert werden Filme dieser Liste automatisch hinzugefügt",
|
||||
"AddImportExclusionHelpText": "Automatisches ( wieder- ) hinzufügen durch Listen verhindern",
|
||||
"AddImportExclusionHelpText": "Automatisches ( wieder- ) hinzufügen zu {appName} durch Listen verhindern",
|
||||
"AgeWhenGrabbed": "Alter (beim erfassen)",
|
||||
"AllowHardcodedSubs": "Hartcodierte Untertitel erlauben",
|
||||
"AlreadyInYourLibrary": "Bereits in deiner Mediathek",
|
||||
@@ -952,12 +952,12 @@
|
||||
"AptUpdater": "Benutze 'apt' um das Update zu installieren",
|
||||
"Always": "Immer",
|
||||
"AllResultsHiddenFilter": "Keine Ergebnisse mit den ausgewählten Filtern",
|
||||
"AllMoviesInPathHaveBeenImported": "Alle Filme in {0} wurden importiert",
|
||||
"AllMoviesInPathHaveBeenImported": "Alle Filme in {path} wurden importiert",
|
||||
"AllFiles": "Alle Dateien",
|
||||
"AfterManualRefresh": "Nach manuellen aktualisieren",
|
||||
"AddToDownloadQueue": "Zur Downloadwarteschlange hinzufügen",
|
||||
"AddRootFolder": "Stammordner hinzufügen",
|
||||
"AddQualityProfile": "Qualitätsprofil hinzufügen",
|
||||
"AddQualityProfile": "Qualitäts Profil hinzufügen",
|
||||
"AddedToDownloadQueue": "Zur Downloadwarteschlange hinzugefügt",
|
||||
"AddDownloadClient": "Downloadmanager hinzufügen",
|
||||
"AddCustomFormat": "Eigenes Format hinzufügen",
|
||||
@@ -1178,7 +1178,7 @@
|
||||
"IMDbId": "TMDb ID",
|
||||
"DisabledForLocalAddresses": "Für Lokale Adressen deaktivieren",
|
||||
"AddCondition": "Bedingung hinzufügen",
|
||||
"AddAutoTag": "Automatisches Tag hinzufügen",
|
||||
"AddAutoTag": "Automatischen Tag hinzufügen",
|
||||
"AppUpdated": "{appName} aktualisiert",
|
||||
"AddConditionImplementation": "Bedingung hinzufügen - {implementationName}",
|
||||
"AddImportList": "Importliste hinzufügen",
|
||||
@@ -1189,5 +1189,16 @@
|
||||
"AddConnectionImplementation": "Verbindung hinzufügen - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Download-Client hinzufügen - {implementationName}",
|
||||
"AddIndexerImplementation": "Indexer hinzufügen - {implementationName}",
|
||||
"AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu"
|
||||
"AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Neues Passwort bestätigen",
|
||||
"AllTitles": "Alle Titel",
|
||||
"AuthenticationRequired": "Authentifizierung benötigt",
|
||||
"AuthenticationRequiredHelpText": "Ändern, welche anfragen Authentifizierung benötigen. Ändere nichts wenn du dir nicht des Risikos bewusst bist.",
|
||||
"AudioLanguages": "Audio Sprachen",
|
||||
"AuthenticationMethodHelpTextWarning": "Bitte wähle eine gültige Authentifizierungsmethode aus",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Gib ein neues Passwort ein",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Gib einen neuen Benutzernamen ein",
|
||||
"AuthenticationRequiredWarning": "Um unberechtigte Fernzugriffe zu vermeiden benötigt {appName} jetzt , dass Authentifizierung eingeschaltet ist. Du kannst Authentifizierung optional für lokale Adressen ausschalten.",
|
||||
"AutoRedownloadFailed": "Erneuter Download fehlgeschlagen",
|
||||
"AutoRedownloadFailedFromInteractiveSearch": "Erneuter Download aus Interaktiver Suche fehlgeschlagen"
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"DownloadClientStatusCheckSingleClientMessage": "Gestores de descargas no disponibles debido a errores: {downloadClientNames}",
|
||||
"DownloadClientStatusCheckAllClientMessage": "Los gestores de descargas no están disponibles debido a errores",
|
||||
"DownloadClients": "Gestores de Descargas",
|
||||
"DownloadClientCheckUnableToCommunicateMessage": "Incapaz de comunicarse con {downloadClientName}.",
|
||||
"DownloadClientCheckUnableToCommunicateMessage": "Incapaz de comunicarse con {downloadClientName}. {errorMessage}",
|
||||
"DownloadClientCheckNoneAvailableMessage": "Ningún gestor de descargas disponible",
|
||||
"DiskSpace": "Espacio en Disco",
|
||||
"Discover": "Descubrir",
|
||||
@@ -632,15 +632,15 @@
|
||||
"EnableInteractiveSearchHelpText": "Se usará cuando se utilice la búsqueda interactiva",
|
||||
"EnableAutomaticSearchHelpText": "Se usará cuando las búsquedas automáticas se realicen desde el UI o por {appName}",
|
||||
"EnableAutomaticSearchHelpTextWarning": "Se usará cuando se utilice la búsqueda interactiva",
|
||||
"DownloadWarning": "Alerta de descarga: {0}",
|
||||
"DownloadWarning": "Alerta de descarga: {warningMessage}",
|
||||
"Downloading": "Descargando",
|
||||
"DownloadFailed": "La descarga ha fallado",
|
||||
"DownloadClientUnavailable": "El gestor de descargas no está disponible",
|
||||
"DeleteTagMessageText": "¿Seguro que quieres eliminar la etiqueta '{label}'?",
|
||||
"DeleteTagMessageText": "¿Está seguro de querer eliminar la etiqueta '{label}'?",
|
||||
"DeleteRestrictionHelpText": "Seguro que quieres eliminar esta restricción?",
|
||||
"DeleteNotificationMessageText": "¿Seguro que quieres eliminiar la notificación '{name}'?",
|
||||
"DeleteNotificationMessageText": "¿Seguro que quieres eliminar la notificación '{name}'?",
|
||||
"DeleteBackupMessageText": "Seguro que quieres eliminar la copia de seguridad '{name}'?",
|
||||
"DeleteDownloadClientMessageText": "¿Seguro que quieres eliminar el cliente de descargas '{name}'?",
|
||||
"DeleteDownloadClientMessageText": "Seguro que quieres eliminar el gestor de descargas '{name}'?",
|
||||
"DeleteIndexerMessageText": "Seguro que quieres eliminar el indexer '{name}'?",
|
||||
"Cutoff": "Requisito",
|
||||
"ClickToChangeMovie": "Clic para cambiar película",
|
||||
@@ -693,7 +693,7 @@
|
||||
"MinutesSixty": "60 Minutos: {0}",
|
||||
"MinutesNinety": "90 Minutos: {0}",
|
||||
"MinutesHundredTwenty": "120 Minutos: {0}",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento: arregla bugs y otras mejoras. Ve a Github Commit History para más detalles",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento: Corrección de errores y otras mejoras. Ver historial de commits de Github para mas detalle",
|
||||
"LoadingMovieFilesFailed": "La carga de los archivos ha fallado",
|
||||
"LoadingMovieExtraFilesFailed": "La carga de los extras de la película ha fallado",
|
||||
"LoadingMovieCreditsFailed": "La carga de los créditos de la película ha fallado",
|
||||
@@ -1132,7 +1132,7 @@
|
||||
"CloneCondition": "Clonar Condición",
|
||||
"DeleteAutoTag": "Eliminar Etiquetado Automático",
|
||||
"DeleteAutoTagHelpText": "¿Está seguro de querer eliminar el etiquetado automático '{name}'?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "¿Estas seguro que quieres eliminar {count} cliente(s) de descarga seleccionado(s)?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "¿Está seguro de querer eliminar {count} cliente(s) de descarga seleccionado(s)?",
|
||||
"EditAutoTag": "Editar Etiquetado Automático",
|
||||
"EditSelectedDownloadClients": "Editar Clientes de Descarga Seleccionados",
|
||||
"EditSelectedIndexers": "Editar Indexadores Seleccionados",
|
||||
@@ -1185,7 +1185,7 @@
|
||||
"DeleteImportListMessageText": "Seguro que quieres eliminar la lista '{name}'?",
|
||||
"DeleteSelectedImportListsMessageText": "Seguro que quieres eliminar {count} lista(s) de importación seleccionada(s)?",
|
||||
"AppUpdatedVersion": "{appName} ha sido actualizado a la versión `{version}`, para obtener los cambios más recientes necesitará recargar {appName}",
|
||||
"DeleteSelectedIndexersMessageText": "Seguro que quieres eliminar {count} indexer seleccionado(s)?",
|
||||
"DeleteSelectedIndexersMessageText": "¿Está seguro de querer eliminar {count} indexador(es) seleccionado(s)?",
|
||||
"DisabledForLocalAddresses": "Desactivado para direcciones locales",
|
||||
"DeletedReasonManual": "El archivo fue borrado por vía UI",
|
||||
"DeletedReasonMissingFromDisk": "{appName} no ha podido encontrar el archivo en el disco, por lo que se ha desvinculado de la película en la base de datos",
|
||||
@@ -1204,5 +1204,32 @@
|
||||
"CopyToClipboard": "Copiar al portapapeles",
|
||||
"CloneCustomFormat": "Clonar formato personalizado",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"Close": "Cerrar"
|
||||
"Close": "Cerrar",
|
||||
"DownloadClientsLoadError": "No se puden cargar los gestores de descargas",
|
||||
"EditConnectionImplementation": "Editar notificación - {implementationName}",
|
||||
"EditImportListImplementation": "Añadir lista de importación - {implementationName}",
|
||||
"EditIndexerImplementation": "Editar indexador - {implementationName}",
|
||||
"FormatShortTimeSpanHours": "{hours} hora(s)",
|
||||
"FormatShortTimeSpanMinutes": "{minutes} minuto(s)",
|
||||
"FormatShortTimeSpanSeconds": "{seconds} segundo(s)",
|
||||
"FormatTimeSpanDays": "{days}d {time}",
|
||||
"EditDownloadClientImplementation": "Añadir Cliente de Descarga - {implementationName}",
|
||||
"EnableProfile": "Habilitar perfil",
|
||||
"FormatAgeDay": "día",
|
||||
"FormatAgeHour": "hora",
|
||||
"FormatAgeHours": "horas",
|
||||
"FormatAgeMinute": "minuto",
|
||||
"FormatAgeMinutes": "minutos",
|
||||
"FormatRuntimeHours": "{hours}h",
|
||||
"FormatRuntimeMinutes": "{minutes}m",
|
||||
"FormatDateTimeRelative": "{relativeDay}, {formattedDate} {formattedTime}",
|
||||
"FormatDateTime": "{formattedDate} {formattedTime}",
|
||||
"UnknownEventTooltip": "Evento desconocído",
|
||||
"FormatAgeDays": "días",
|
||||
"False": "Falso",
|
||||
"DownloadIgnored": "Descarga ignorada",
|
||||
"FailedToFetchUpdates": "Fallo al buscar las actualizaciones",
|
||||
"FailedToUpdateSettings": "Fallo al actualizar los ajustes",
|
||||
"EditConditionImplementation": "Editar Condición - {implementationName}",
|
||||
"DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "El cliente de descarga {downloadClientName} esta configurado para eliminar las descargas completadas. Esto puede causar que las descargas sean eliminadas del cliente antes que {1} las pueda importar."
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"IndexerStatusCheckAllClientMessage": "Tous les indexeurs sont indisponibles en raison d'échecs",
|
||||
"IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, {appName} ne fournira aucun résultat de recherche interactive",
|
||||
"IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, {appName} ne fournira aucun résultat de recherche interactif",
|
||||
"IndexerSearchCheckNoAvailableIndexersMessage": "Tous les indexeurs compatibles avec la recherche sont temporairement indisponibles en raison d'erreurs d'indexation récentes",
|
||||
"IndexerSearchCheckNoAutomaticMessage": "Aucun indexeur disponible avec la recherche automatique activée, {appName} ne fournira aucun résultat de recherche automatique",
|
||||
"Indexers": "Indexeurs",
|
||||
"ImportTipsMessage": "Quelques conseils pour assurer le bon déroulement de l'importation :",
|
||||
"ImportMechanismHealthCheckMessage": "Activer la gestion des téléchargements terminés",
|
||||
"ImportHeader": "Importez une bibliothèque organisée existante pour ajouter des films à {appName}",
|
||||
"ImportHeader": "Importer une bibliothèque organisée existante pour ajouter des films à {appName}",
|
||||
"Import": "Importer",
|
||||
"iCalLink": "Lien iCal",
|
||||
"Host": "Hôte",
|
||||
"History": "Historique",
|
||||
"HideAdvanced": "Masquer param. av.",
|
||||
"HideAdvanced": "Masquer les Options Avancées",
|
||||
"Health": "Santé",
|
||||
"GrabSelected": "Saisir la sélection",
|
||||
"General": "Général",
|
||||
@@ -55,13 +55,13 @@
|
||||
"AddNewMessage": "C'est facile d'ajouter un nouveau film, vous n'avez juste qu'à saisir le nom du film que vous voulez ajouter",
|
||||
"AddMovies": "Ajouter des films",
|
||||
"AddExclusion": "Ajouter une exclusion",
|
||||
"AddNew": "Ajouter une nouvelle",
|
||||
"AddNew": "Ajouter un élément",
|
||||
"Activity": "Activité",
|
||||
"About": "À propos",
|
||||
"CustomFormatsSettingsSummary": "Paramètres de formats personnalisés",
|
||||
"IndexerStatusCheckSingleClientMessage": "Indexeurs indisponibles en raison d'échecs : {indexerNames}",
|
||||
"DownloadClientStatusCheckSingleClientMessage": "Clients de Téléchargement indisponibles en raison d'échecs : {downloadClientNames}",
|
||||
"SetTags": "Définir des balises",
|
||||
"SetTags": "Définir des étiquettes",
|
||||
"ReleaseTitle": "Titre de la version",
|
||||
"ReleaseStatus": "Statut de la version",
|
||||
"ReleaseGroup": "Groupe de versions",
|
||||
@@ -71,7 +71,7 @@
|
||||
"UnselectAll": "Tout désélectionner",
|
||||
"Unmonitored": "Non surveillé",
|
||||
"UISettingsSummary": "Calendrier, date et les options d'altération des couleurs",
|
||||
"TagsSettingsSummary": "Voir toutes les balises et comment elles sont utilisées. Les balises inutilisées peuvent être supprimées",
|
||||
"TagsSettingsSummary": "Voir toutes les étiquettes et comment elles sont utilisées. Les étiquettes inutilisées peuvent être supprimées",
|
||||
"Style": "Style",
|
||||
"Studio": "Studio",
|
||||
"Status": "État",
|
||||
@@ -99,7 +99,7 @@
|
||||
"Restrictions": "Restrictions",
|
||||
"RestoreBackup": "Restaurer la sauvegarde",
|
||||
"RenameFiles": "Renommer les fichiers",
|
||||
"Renamed": "Renommer",
|
||||
"Renamed": "Renommé",
|
||||
"RemoveSelected": "Enlever la sélection",
|
||||
"RemovedMovieCheckSingleMessage": "Le film {movie} a été supprimé de TMDb",
|
||||
"RemovedMovieCheckMultipleMessage": "Les films {movies} ont été supprimés de TMDb",
|
||||
@@ -141,7 +141,7 @@
|
||||
"MountCheckMessage": "Le montage contenant un chemin de film est monté en lecture seule : ",
|
||||
"MoreInfo": "Plus d'informations",
|
||||
"Month": "Mois",
|
||||
"ListsSettingsSummary": "Importer listes, listes d'exclusions",
|
||||
"ListsSettingsSummary": "Importer des Listes, exclure des listes",
|
||||
"ListExclusions": "Liste des exclusions",
|
||||
"IndexersSettingsSummary": "Indexeurs et restrictions de version",
|
||||
"Grabbed": "Saisie",
|
||||
@@ -235,7 +235,7 @@
|
||||
"RejectionCount": "Nombre de rejets",
|
||||
"Peers": "Peers",
|
||||
"Organize": "Organiser",
|
||||
"Ok": "Ok",
|
||||
"Ok": "OK",
|
||||
"OAuthPopupMessage": "Les pop-ups sont bloquées par votre navigateur",
|
||||
"Name": "Nom",
|
||||
"MoveFiles": "Déplacer des fichiers",
|
||||
@@ -248,7 +248,7 @@
|
||||
"NoIssuesWithYourConfiguration": "Aucun problème avec votre configuration",
|
||||
"HardlinkCopyFiles": "Lien physique/Copie de fichiers",
|
||||
"Extension": "Extension",
|
||||
"CustomFormatScore": "Partition au format personnalisé",
|
||||
"CustomFormatScore": "Score du format personnalisé",
|
||||
"SystemTimeCheckMessage": "L'heure du système est décalée de plus d'un jour. Les tâches planifiées peuvent ne pas s'exécuter correctement tant que l'heure ne sera pas corrigée",
|
||||
"ShowMonitored": "Afficher le chemin",
|
||||
"SettingsWeekColumnHeaderHelpText": "Affiché au dessus de chaque colonne quand \"Semaine\" est l'affichage actif",
|
||||
@@ -282,7 +282,7 @@
|
||||
"SearchMovie": "Rechercher le film",
|
||||
"RecentFolders": "Dossiers récents",
|
||||
"QuickImport": "Déplacer automatiquement",
|
||||
"PosterSize": "Poster taille",
|
||||
"PosterSize": "Taille des affiches",
|
||||
"Posters": "Affiches",
|
||||
"PosterOptions": "Poster options",
|
||||
"PendingChangesStayReview": "Rester et vérifier les modifications",
|
||||
@@ -415,7 +415,7 @@
|
||||
"BranchUpdateMechanism": "Branche utilisée par le mécanisme de mise à jour extérieur",
|
||||
"BranchUpdate": "Branche à utiliser pour mettre à jour {appName}",
|
||||
"BeforeUpdate": "Avant la mise à jour",
|
||||
"ApplyTagsHelpTextHowToApplyMovies": "Comment appliquer des tags au film sélectionné",
|
||||
"ApplyTagsHelpTextHowToApplyMovies": "Comment appliquer des étiquettes aux films sélectionnés",
|
||||
"DeleteDownloadClientMessageText": "Voulez-vous supprimer le client de téléchargement « {name} » ?",
|
||||
"DeleteBackupMessageText": "Voulez-vous supprimer la sauvegarde « {name} » ?",
|
||||
"ErrorLoadingContents": "Erreur lors du chargement du contenu",
|
||||
@@ -543,15 +543,15 @@
|
||||
"GrabReleaseMessageText": "{appName} n'a pas été en mesure de déterminer à quel film cette version était destinée. {appName} peut être incapable d'importer automatiquement cette version. Voulez-vous récupérer '{0}' ?",
|
||||
"ExtraFileExtensionsHelpTexts1": "Liste séparée par des virgules des fichiers supplémentaires à importer (.nfo sera importé en tant que .nfo-orig)",
|
||||
"YouCanAlsoSearch": "Vous pouvez également effectuer une recherche à l'aide de l'ID TMDb ou de l'ID IMDb d'un film. par exemple : `tmdb:71663`",
|
||||
"WhitelistedSubtitleTags": "Balises de sous-titres sur liste blanche",
|
||||
"WhitelistedHardcodedSubsHelpText": "Les balises de sous-titres définies ici ne seront pas considérées comme codées en dur",
|
||||
"WhitelistedSubtitleTags": "Étiquettes de sous-titres sur liste blanche",
|
||||
"WhitelistedHardcodedSubsHelpText": "Les étiquettes de sous-titres définies ici ne seront pas considérées comme codées en dur",
|
||||
"WeekColumnHeader": "En-tête de colonne de la semaine",
|
||||
"UsenetDelayHelpText": "Délai en minutes avant de récupérer une release de Usenet",
|
||||
"Uptime": "Disponibilité",
|
||||
"UpgradeUntilThisQualityIsMetOrExceeded": "Mise à niveau jusqu'à ce que cette qualité soit atteinte ou dépassée",
|
||||
"UpgradeAllowedHelpText": "Si désactivé, les qualités ne seront pas améliorées",
|
||||
"UpdateScriptPathHelpText": "Chemin d'accès à un script personnalisé qui prend un package de mise à jour extrait et gère le reste du processus de mise à jour",
|
||||
"UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré de {appName} ou un script",
|
||||
"UpdateMechanismHelpText": "Utilisez le programme de mise à jour intégré de {appName} ou un script",
|
||||
"UpdateAutomaticallyHelpText": "Téléchargez et installez automatiquement les mises à jour. Vous pourrez toujours installer à partir du système : mises à jour",
|
||||
"Unreleased": "Version non disponible",
|
||||
"UnmonitoredHelpText": "Inclure les films non surveillés dans le flux iCal",
|
||||
@@ -843,7 +843,7 @@
|
||||
"Hours": "Heures",
|
||||
"HomePage": "Page d'accueil",
|
||||
"HttpHttps": "HTTP(S)",
|
||||
"ImportLibrary": "Import bibliothèque",
|
||||
"ImportLibrary": "Importer biblio.",
|
||||
"MovieIsRecommend": "Le film est recommandé en fonction de l'ajout récent",
|
||||
"NoAltTitle": "Pas de titres alternatifs.",
|
||||
"NoLinks": "Aucun liens",
|
||||
@@ -1034,7 +1034,7 @@
|
||||
"OriginalLanguage": "Langue originale",
|
||||
"Rating": "Notation",
|
||||
"RemotePath": "Chemin distant",
|
||||
"RemotePathMappingCheckFilesBadDockerPath": "Vous utilisez docker ; {0} signifie les téléchargement dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
|
||||
"RemotePathMappingCheckFilesBadDockerPath": "Vous utilisez Docker ; le client de téléchargement {downloadClientName} a signalé des fichiers dans {path}, mais ce n'est pas un chemin valide pour {osName}. Vérifiez vos mappages de chemins distants et les paramètres de votre client de téléchargement.",
|
||||
"RemotePathMappingCheckWrongOSPath": "Le client de téléchargement distant {downloadClientName} met les téléchargements dans {path} mais ce chemin {osName} est invalide. Vérifiez vos paramètres de chemins distants et les paramètres de votre client de téléchargement.",
|
||||
"RemoveCompleted": "Supprimer terminé",
|
||||
"Database": "Base de données",
|
||||
@@ -1238,7 +1238,7 @@
|
||||
"MovieImported": "Film importé",
|
||||
"SelectDropdown": "Sélectionner...",
|
||||
"SelectLanguageModalTitle": "{modalTitle} – Sélectionner la langue",
|
||||
"RemoveTagsAutomatically": "Supprimer les balises automatiquement",
|
||||
"RemoveTagsAutomatically": "Supprimer automatiquement les étiquettes",
|
||||
"TablePageSizeHelpText": "Nombre d'éléments à afficher sur chaque page",
|
||||
"UnknownEventTooltip": "Événement inconnu",
|
||||
"AppUpdated": "{appName} mis à jour",
|
||||
@@ -1254,8 +1254,8 @@
|
||||
"OrganizeLoadError": "Erreur lors du chargement des aperçus",
|
||||
"EditImportListImplementation": "Modifier la liste d'importation - {implementationName}",
|
||||
"EditIndexerImplementation": "Modifier l'indexeur - {implementationName}",
|
||||
"MovieFileDeleted": "À la suppression d'un fichier vidéo",
|
||||
"MovieFileDeletedTooltip": "À la suppression d'un fichier vidéo",
|
||||
"MovieFileDeleted": "Fichier du film supprimé",
|
||||
"MovieFileDeletedTooltip": "Fichier du film supprimé",
|
||||
"BlocklistReleaseHelpText": "Empêche {appName} de récupérer automatiquement cette version",
|
||||
"InteractiveImportLoadError": "Impossible de charger les éléments d'importation manuelle",
|
||||
"MovieSearchResultsLoadError": "Impossible de charger les résultats de cette recherche de films. Réessayez plus tard",
|
||||
@@ -1322,7 +1322,7 @@
|
||||
"MovieGrabbedHistoryTooltip": "Film extrait de {indexer} et envoyé à {downloadClient}",
|
||||
"RemoveQueueItem": "Supprimer – {sourceTitle}",
|
||||
"OverrideGrabModalTitle": "Remplacer et récupérer - {title}",
|
||||
"RemoveTagsAutomaticallyHelpText": "Supprimez automatiquement les balises si les conditions ne sont pas remplies",
|
||||
"RemoveTagsAutomaticallyHelpText": "Supprimez automatiquement les étiquettes si les conditions ne sont pas remplies",
|
||||
"InfoUrl": "URL d'informations",
|
||||
"ListRefreshInterval": "Intervalle d'actualisation de la liste",
|
||||
"Parse": "Analyser",
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
{}
|
||||
{
|
||||
"About": "Par",
|
||||
"AcceptConfirmationModal": "Apstiprināt Apstiprināšanas Modālu",
|
||||
"Actions": "Darbības",
|
||||
"Activity": "Aktivitāte",
|
||||
"Add": "Pievienot",
|
||||
"AddAutoTag": "Pievienot Automātisko Tagu",
|
||||
"AddCondition": "Pievienot Nosacījumu",
|
||||
"AddCustomFormat": "Pievienot Pielāgotu Formātu",
|
||||
"AddConditionImplementation": "Pievienot Nosacījumu - {implementationName}",
|
||||
"AddConnection": "Pievienot Savienojumu",
|
||||
"AddConnectionImplementation": "Pievienot Savienojumu - {implementationName}",
|
||||
"AddDelayProfile": "Pievienot Aizkaves Profilu",
|
||||
"AddDownloadClient": "Pievienot Lejupielādes Klientu"
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
"AddNewTmdbIdMessage": "Je kunt ook zoeken met het TMDb id van een film. Bijv. tmdb:71663",
|
||||
"AddNewMessage": "Het is gemakkelijk om een nieuwe film toe te voegen, begin gewoon met de naam te typen van de film die je wilt toevoegen",
|
||||
"AddNew": "Nieuwe toevoegen",
|
||||
"AddExclusion": "Uitzondering toevoegen",
|
||||
"AddExclusion": "Uitzondering Toevoegen",
|
||||
"AddMovies": "Film(s) Toevoegen",
|
||||
"Activity": "Activiteit",
|
||||
"About": "Over",
|
||||
@@ -645,9 +645,9 @@
|
||||
"DeleteTagMessageText": "Bent u zeker dat u de tag '{0}' wilt verwijderen?",
|
||||
"DeleteRestrictionHelpText": "Bent u zeker dat u deze restrictie wilt verwijderen?",
|
||||
"DeleteNotificationMessageText": "Bent u zeker dat u de notificatie '{0}' wilt verwijderen?",
|
||||
"DeleteIndexerMessageText": "Bent u zeker dat u de indexeerder '{0}' wilt verwijderen?",
|
||||
"DeleteDownloadClientMessageText": "Bent u zeker dat u de downloader '{0}' wilt verwijderen?",
|
||||
"DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{0}' wilt verwijderen?",
|
||||
"DeleteIndexerMessageText": "Bent u zeker dat u de indexeerder '{name}' wilt verwijderen?",
|
||||
"DeleteDownloadClientMessageText": "Bent u zeker dat u de downloader '{name}' wilt verwijderen?",
|
||||
"DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{name}' wilt verwijderen?",
|
||||
"Cutoff": "Drempel",
|
||||
"ClickToChangeMovie": "Klik om film te wijzigen",
|
||||
"CheckDownloadClientForDetails": "controleer downloader voor meer details",
|
||||
@@ -692,7 +692,7 @@
|
||||
"ForMoreInformationOnTheIndividualDownloadClients": "Voor meer informatie over de individuele download applicaties, klik op de info knoppen.",
|
||||
"FailedLoadingSearchResults": "Laden van zoekresultaten is mislukt, gelieve opnieuw te proberen.",
|
||||
"ExtraFileExtensionsHelpTexts1": "Komma gescheiden lijst met extra bestanden om te importeren (.nfo zal als .nfo-orig worden geïmporteerd)",
|
||||
"CouldNotFindResults": "Kon geen resultaten vinden voor '{0}'",
|
||||
"CouldNotFindResults": "Kon geen resultaten vinden voor '{term}'",
|
||||
"ApplyTagsHelpTextHowToApplyMovies": "Hoe tags toe te passen op de geselecteerd films",
|
||||
"BackupsLoadError": "Kon geen veiligheidskopieën laden",
|
||||
"TagIsNotUsedAndCanBeDeleted": "Tag is niet in gebruik en kan verwijderd worden",
|
||||
@@ -1102,10 +1102,10 @@
|
||||
"DownloadClientTagHelpText": "Gebruik deze indexer alleen voor films met ten minste één overeenkomende tag. Laat leeg om te gebruiken met alle films.",
|
||||
"DeleteDelayProfileMessageText": "Weet u zeker dat u dit vertragingsprofiel wilt verwijderen?",
|
||||
"RemoveSelectedItemQueueMessageText": "Weet je zeker dat je {0} van de wachtrij wilt verwijderen?",
|
||||
"CountIndexersSelected": "{0} Indexer(s) Geselecteerd",
|
||||
"CountIndexersSelected": "{count} Indexer(s) Geselecteerd",
|
||||
"DeleteSelectedIndexers": "Verwijder Indexeerder",
|
||||
"ResetAPIKeyMessageText": "Bent u zeker dat u uw API-sleutel wilt resetten?",
|
||||
"DeleteConditionMessageText": "Bent u zeker dat u de lijst '{0}' wilt verwijderen?",
|
||||
"DeleteConditionMessageText": "Bent u zeker dat u de lijst '{name}' wilt verwijderen?",
|
||||
"DeleteCustomFormatMessageText": "Bent u zeker dat u de indexeerder '{customFormatName}' wilt verwijderen?",
|
||||
"DeleteFormatMessageText": "Weet je zeker dat je formaat tag {0} wilt verwijderen?",
|
||||
"DeleteImportListExclusionMessageText": "Bent u zeker dat u dit van de uitzonderingenlijst wilt verwijderen?",
|
||||
@@ -1128,7 +1128,7 @@
|
||||
"AddConditionImplementation": "Voeg voorwaarde toe - {implementationName}",
|
||||
"AddConnection": "Voeg connectie toe",
|
||||
"AddConnectionImplementation": "Voeg connectie toe - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Voeg Downloadclient toe - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Voeg Downloadclient Toe - {implementationName}",
|
||||
"AddIndexerImplementation": "Indexeerder toevoegen - {implementationName}",
|
||||
"DeleteQualityProfileMessageText": "Bent u zeker dat u het kwaliteitsprofiel {name} wilt verwijderen?",
|
||||
"AppUpdated": "{appName} is geüpdatet",
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
"Cancel": "Cancelar",
|
||||
"Calendar": "Calendário",
|
||||
"BackupNow": "Criar cópia de segurança",
|
||||
"Backup": "Cópia de segurança",
|
||||
"Backup": "Backup",
|
||||
"AudioInfo": "Informações do áudio",
|
||||
"Apply": "Aplicar",
|
||||
"Analytics": "Análise",
|
||||
@@ -468,7 +468,7 @@
|
||||
"BindAddressHelpText": "Endereço de IP válido, localhost ou \"*\" para todas as interfaces",
|
||||
"BindAddress": "Endereço de vínculo",
|
||||
"Backups": "Cópias de segurança",
|
||||
"BackupFolderHelpText": "Caminhos relativos estarão na pasta AppData do {appName}",
|
||||
"BackupFolderHelpText": "Caminhos relativos estarão no diretório AppData do {appName}",
|
||||
"BackupIntervalHelpText": "Intervalo entre cópias de segurança automáticas",
|
||||
"BackupRetentionHelpText": "Cópias de segurança automáticas anteriores ao período de retenção serão eliminadas automaticamente",
|
||||
"Cutoff": "Limite",
|
||||
@@ -1189,5 +1189,6 @@
|
||||
"DeleteImportList": "Eliminar Lista de Importação",
|
||||
"DeleteImportListMessageText": "Tem a certeza de que pretende eliminar a lista '{name}'?",
|
||||
"DownloadClientRemovesCompletedDownloadsHealthCheckMessage": "O cliente de descarregamento {downloadClientName} está definido para remover descarregamentos concluídos. Isto pode fazer com que as transferências sejam removidas do seu cliente antes de {1} as poder importar.",
|
||||
"AppUpdated": "{appName} Atualizado"
|
||||
"AppUpdated": "{appName} Atualizado",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirmar nova senha"
|
||||
}
|
||||
|
||||
@@ -1006,6 +1006,9 @@
|
||||
"DeleteRemotePathMappingMessageText": "Bu uzak yol eşlemesini silmek istediğinizden emin misiniz?",
|
||||
"AddAutoTag": "Otomatik Etiket Ekle",
|
||||
"AddCondition": "Koşul Ekle",
|
||||
"AddConditionImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"AddConnection": "Bağlantı Ekle"
|
||||
"AddConditionImplementation": "Koşul Ekle - {implementationName}",
|
||||
"AddConnection": "Bağlantı Ekle",
|
||||
"AddIndexerImplementation": "Koşul Ekle - {implementationName}",
|
||||
"AddConnectionImplementation": "Koşul Ekle - {implementationName}",
|
||||
"EditIndexerImplementation": "Koşul Ekle - {implementationName}"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"About": "关于",
|
||||
"DownloadClientCheckUnableToCommunicateMessage": "无法与{downloadClientName}进行通讯。",
|
||||
"DownloadClientCheckUnableToCommunicateMessage": "无法与{downloadClientName}进行通讯:{errorMessage}",
|
||||
"DownloadClientCheckNoneAvailableMessage": "无可用的下载客户端",
|
||||
"DownloadClient": "下载客户端",
|
||||
"Donations": "赞助",
|
||||
@@ -70,7 +70,7 @@
|
||||
"AuthForm": "表单(登陆页面)",
|
||||
"AuthBasic": "基础(浏览器弹出对话框)",
|
||||
"AppDataDirectory": "AppData目录",
|
||||
"ApiKey": "API Key",
|
||||
"ApiKey": "接口密钥 (API Key)",
|
||||
"Backups": "历史备份",
|
||||
"BindAddress": "绑定地址",
|
||||
"BranchUpdate": "更新{appName}的分支",
|
||||
@@ -294,7 +294,7 @@
|
||||
"Monday": "星期一",
|
||||
"MissingNotMonitored": "缺少(未监控)",
|
||||
"MissingMonitoredAndConsideredAvailable": "缺少(监控中)",
|
||||
"Missing": "缺少",
|
||||
"Missing": "缺失",
|
||||
"MinutesSixty": "60分钟: {0}",
|
||||
"MinutesNinety": "90分钟: {0}",
|
||||
"MinutesHundredTwenty": "120分钟: {0}",
|
||||
@@ -394,8 +394,8 @@
|
||||
"Ended": "已完结",
|
||||
"Error": "错误",
|
||||
"EnableSslHelpText": " 重启生效",
|
||||
"EnableSSL": "启用SSL",
|
||||
"EnableRSS": "启用RSS",
|
||||
"EnableSSL": "启用 SSL",
|
||||
"EnableRSS": "启用 RSS",
|
||||
"EnableInteractiveSearchHelpTextWarning": "该索引器不支持搜索",
|
||||
"EnableInteractiveSearchHelpText": "当手动搜索启用时使用",
|
||||
"EnableInteractiveSearch": "启用手动搜索",
|
||||
@@ -735,7 +735,7 @@
|
||||
"ReleaseRejected": "发布被拒绝",
|
||||
"UnmappedFilesOnly": "仅限未映射的文件",
|
||||
"Quality": "媒体质量",
|
||||
"TheLogLevelDefault": "默认的日志等级为“Info”,可以被修改在",
|
||||
"TheLogLevelDefault": "默认的日志等级为 \"Info\", 可以在 [常规设置] 中修改 (/settings/general)",
|
||||
"RestartReloadNote": "注意:{appName}将在恢复过程中自动重启并重新加载UI。",
|
||||
"RequiredRestrictionPlaceHolder": "添加新限制",
|
||||
"PhysicalRelease": "碟片版发布日期",
|
||||
@@ -882,7 +882,7 @@
|
||||
"UsenetDisabled": "Usenet已关闭",
|
||||
"VisitGithubCustomFormatsAphrodite": "访问wiki获取更多详细信息: ",
|
||||
"WaitingToProcess": "等待处理",
|
||||
"Wanted": "想要的",
|
||||
"Wanted": "已追踪",
|
||||
"Warn": "警告",
|
||||
"Week": "周",
|
||||
"WhitelistedHardcodedSubsHelpText": "这里设置的字幕标签不会被认为是硬编码的",
|
||||
@@ -982,7 +982,7 @@
|
||||
"DownloadClientCheckDownloadingToRoot": "下载客户端{downloadClientName}将下载内容放在根文件夹{path}中。您不应该下载到根文件夹。",
|
||||
"DeleteFileLabel": "删除 {0} 电影文件",
|
||||
"ImportListMultipleMissingRoots": "导入列表中缺失多个根目录文件夹",
|
||||
"ImportListMissingRoot": "在导入列表中缺少根目录文件夹",
|
||||
"ImportListMissingRoot": "在导入列表中缺少根目录文件夹: {rootFolderInfo}",
|
||||
"BypassDelayIfHighestQuality": "如果达到最高质量,则跳过",
|
||||
"NotificationTriggersHelpText": "选择触发此通知的事件",
|
||||
"From": "来自",
|
||||
@@ -1004,7 +1004,7 @@
|
||||
"RemoveFromBlocklist": "从黑名单中移除",
|
||||
"Blocklisted": "黑名单",
|
||||
"BlocklistReleases": "黑名单版本",
|
||||
"IndexerTagHelpText": "仅对至少有一个匹配标记的电影使用此索引器。留空则适用于所有电影。",
|
||||
"IndexerTagHelpText": "仅对至少有一个匹配标签的电影使用此索引器。留空则适用于所有电影。",
|
||||
"RemotePathMappingCheckFileRemoved": "文件{path} 在处理的过程中被部分删除。",
|
||||
"RemotePathMappingCheckFilesGenericPermissions": "下载{1}中客户端{0}报告的文件,但{appName}无法看到此目录。您可能需要调整文件夹的权限。",
|
||||
"RemotePathMappingCheckGenericPermissions": "下载客户端{downloadClientName}将下载放置在{path}中,但 {appName} 无法看到此目录。您可能需要调整文件夹的权限。",
|
||||
@@ -1338,5 +1338,13 @@
|
||||
"ClearBlocklist": "清空黑名单",
|
||||
"ClearBlocklistMessageText": "你确定要将黑名单中的所有项目清空吗?",
|
||||
"PasswordConfirmation": "确认密码",
|
||||
"InteractiveSearchModalHeader": "交互式搜索"
|
||||
"InteractiveSearchModalHeader": "交互式搜索",
|
||||
"UpdaterLogFiles": "更新器日志文件",
|
||||
"EnableProfile": "启用配置",
|
||||
"FailedToFetchUpdates": "获取更新失败",
|
||||
"FailedToUpdateSettings": "更新配置失败",
|
||||
"WhySearchesCouldBeFailing": "单击此处了解搜索失败的原因",
|
||||
"LogFilesLocation": "日志文件位于: {location}",
|
||||
"PackageVersionInfo": "{packageVersion} 由 {packageAuthor} 制作",
|
||||
"PreviouslyInstalled": "上次安装"
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
DolbyVision,
|
||||
DolbyVisionHdr10,
|
||||
DolbyVisionSdr,
|
||||
DolbyVisionHlg
|
||||
DolbyVisionHlg,
|
||||
DolbyVisionHdr10Plus
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,6 +320,8 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
return "DV";
|
||||
case HdrFormat.DolbyVisionHdr10:
|
||||
return "DV HDR10";
|
||||
case HdrFormat.DolbyVisionHdr10Plus:
|
||||
return "DV HDR10Plus";
|
||||
case HdrFormat.DolbyVisionHlg:
|
||||
return "DV HLG";
|
||||
case HdrFormat.DolbyVisionSdr:
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
private readonly List<FFProbePixelFormat> _pixelFormats;
|
||||
|
||||
public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 8;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 10;
|
||||
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 11;
|
||||
|
||||
private static readonly string[] ValidHdrColourPrimaries = { "bt2020" };
|
||||
private static readonly string[] HlgTransferFunctions = { "bt2020-10", "arib-std-b67" };
|
||||
@@ -188,12 +188,14 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
|
||||
|
||||
if (TryGetSideData<DoviConfigurationRecordSideData>(sideData, out var dovi))
|
||||
{
|
||||
var hasHdr10Plus = TryGetSideData<HdrDynamicMetadataSpmte2094>(sideData, out _);
|
||||
|
||||
return dovi.DvBlSignalCompatibilityId switch
|
||||
{
|
||||
1 => HdrFormat.DolbyVisionHdr10,
|
||||
1 => hasHdr10Plus ? HdrFormat.DolbyVisionHdr10Plus : HdrFormat.DolbyVisionHdr10,
|
||||
2 => HdrFormat.DolbyVisionSdr,
|
||||
4 => HdrFormat.DolbyVisionHlg,
|
||||
6 => HdrFormat.DolbyVisionHdr10,
|
||||
6 => hasHdr10Plus ? HdrFormat.DolbyVisionHdr10Plus : HdrFormat.DolbyVisionHdr10,
|
||||
_ => HdrFormat.DolbyVision
|
||||
};
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace NzbDrone.Core.Notifications.Mailgun
|
||||
const string body = "This is a test message from Radarr, though Mailgun.";
|
||||
|
||||
_proxy.SendNotification(title, body, Settings);
|
||||
_logger.Info("Successsfully sent email though Mailgun.");
|
||||
_logger.Info("Successfully sent email though Mailgun.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||
[FieldDefinition(3, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
|
||||
public string ApiKey { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Send Notifications", HelpText = "Have MediaBrowser send notfications to configured providers", Type = FieldType.Checkbox)]
|
||||
[FieldDefinition(4, Label = "Send Notifications", HelpText = "Have MediaBrowser send notifications to configured providers", Type = FieldType.Checkbox)]
|
||||
public bool Notify { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Update Library", HelpText = "Update Library on Import, Rename or Delete?", Type = FieldType.Checkbox)]
|
||||
|
||||
@@ -8,10 +8,16 @@ namespace NzbDrone.Core.Notifications.Trakt.Resource
|
||||
[JsonProperty(PropertyName = "collected_at")]
|
||||
public DateTime CollectedAt { get; set; }
|
||||
public string Resolution { get; set; }
|
||||
public string Hdr { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "audio_channels")]
|
||||
public string AudioChannels { get; set; }
|
||||
public string Audio { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "media_type")]
|
||||
public string MediaType { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "3d")]
|
||||
public bool Is3D { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ namespace NzbDrone.Core.Notifications.Trakt
|
||||
};
|
||||
|
||||
var traktResolution = MapResolution(movieFile.Quality.Quality.Resolution, movieFile.MediaInfo?.ScanType);
|
||||
var hdr = MapHdr(movieFile);
|
||||
var mediaType = MapMediaType(movieFile.Quality.Quality.Source);
|
||||
var audio = MapAudio(movieFile);
|
||||
var audioChannels = MapAudioChannels(movieFile);
|
||||
@@ -164,9 +165,11 @@ namespace NzbDrone.Core.Notifications.Trakt
|
||||
Year = movie.Year,
|
||||
CollectedAt = DateTime.Now,
|
||||
Resolution = traktResolution,
|
||||
Hdr = hdr,
|
||||
MediaType = mediaType,
|
||||
AudioChannels = audioChannels,
|
||||
Audio = audio,
|
||||
Is3D = movieFile.MediaInfo?.VideoMultiViewCount > 1,
|
||||
Ids = new TraktMovieIdsResource
|
||||
{
|
||||
Tmdb = movie.MovieMetadata.Value.TmdbId,
|
||||
@@ -200,119 +203,76 @@ namespace NzbDrone.Core.Notifications.Trakt
|
||||
|
||||
private string MapMediaType(QualitySource source)
|
||||
{
|
||||
var traktSource = string.Empty;
|
||||
|
||||
switch (source)
|
||||
var traktSource = source switch
|
||||
{
|
||||
case QualitySource.BLURAY:
|
||||
traktSource = "bluray";
|
||||
break;
|
||||
case QualitySource.WEBDL:
|
||||
traktSource = "digital";
|
||||
break;
|
||||
case QualitySource.WEBRIP:
|
||||
traktSource = "digital";
|
||||
break;
|
||||
case QualitySource.DVD:
|
||||
traktSource = "dvd";
|
||||
break;
|
||||
case QualitySource.TV:
|
||||
traktSource = "dvd";
|
||||
break;
|
||||
}
|
||||
QualitySource.BLURAY => "bluray",
|
||||
QualitySource.WEBDL => "digital",
|
||||
QualitySource.WEBRIP => "digital",
|
||||
QualitySource.DVD => "dvd",
|
||||
QualitySource.TV => "dvd",
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
return traktSource;
|
||||
}
|
||||
|
||||
private string MapResolution(int resolution, string scanType)
|
||||
{
|
||||
var traktResolution = string.Empty;
|
||||
var scanIdentifier = scanType.IsNotNullOrWhiteSpace() && TraktInterlacedTypes.InterlacedTypes.Contains(scanType) ? "i" : "p";
|
||||
|
||||
var scanIdentifier = scanType.IsNotNullOrWhiteSpace() && TraktInterlacedTypes.interlacedTypes.Contains(scanType) ? "i" : "p";
|
||||
|
||||
switch (resolution)
|
||||
var traktResolution = resolution switch
|
||||
{
|
||||
case 2160:
|
||||
traktResolution = "uhd_4k";
|
||||
break;
|
||||
case 1080:
|
||||
traktResolution = $"hd_1080{scanIdentifier}";
|
||||
break;
|
||||
case 720:
|
||||
traktResolution = "hd_720p";
|
||||
break;
|
||||
case 576:
|
||||
traktResolution = $"sd_576{scanIdentifier}";
|
||||
break;
|
||||
case 480:
|
||||
traktResolution = $"sd_480{scanIdentifier}";
|
||||
break;
|
||||
}
|
||||
2160 => "uhd_4k",
|
||||
1080 => $"hd_1080{scanIdentifier}",
|
||||
720 => "hd_720p",
|
||||
576 => $"sd_576{scanIdentifier}",
|
||||
480 => $"sd_480{scanIdentifier}",
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
return traktResolution;
|
||||
}
|
||||
|
||||
private string MapHdr(MovieFile movieFile)
|
||||
{
|
||||
var traktHdr = movieFile.MediaInfo?.VideoHdrFormat switch
|
||||
{
|
||||
HdrFormat.DolbyVision or HdrFormat.DolbyVisionSdr => "dolby_vision",
|
||||
HdrFormat.Hdr10 or HdrFormat.DolbyVisionHdr10 => "hdr10",
|
||||
HdrFormat.Hdr10Plus or HdrFormat.DolbyVisionHdr10Plus => "hdr10_plus",
|
||||
HdrFormat.Hlg10 or HdrFormat.DolbyVisionHlg => "hlg",
|
||||
_ => null
|
||||
};
|
||||
|
||||
return traktHdr;
|
||||
}
|
||||
|
||||
private string MapAudio(MovieFile movieFile)
|
||||
{
|
||||
var traktAudioFormat = string.Empty;
|
||||
|
||||
var audioCodec = movieFile.MediaInfo != null ? MediaInfoFormatter.FormatAudioCodec(movieFile.MediaInfo, movieFile.SceneName) : string.Empty;
|
||||
|
||||
switch (audioCodec)
|
||||
var traktAudioFormat = audioCodec switch
|
||||
{
|
||||
case "AC3":
|
||||
traktAudioFormat = "dolby_digital";
|
||||
break;
|
||||
case "EAC3":
|
||||
traktAudioFormat = "dolby_digital_plus";
|
||||
break;
|
||||
case "TrueHD":
|
||||
traktAudioFormat = "dolby_truehd";
|
||||
break;
|
||||
case "EAC3 Atmos":
|
||||
traktAudioFormat = "dolby_digital_plus_atmos";
|
||||
break;
|
||||
case "TrueHD Atmos":
|
||||
traktAudioFormat = "dolby_atmos";
|
||||
break;
|
||||
case "DTS":
|
||||
case "DTS-ES":
|
||||
traktAudioFormat = "dts";
|
||||
break;
|
||||
case "DTS-HD MA":
|
||||
traktAudioFormat = "dts_ma";
|
||||
break;
|
||||
case "DTS-HD HRA":
|
||||
traktAudioFormat = "dts_hr";
|
||||
break;
|
||||
case "DTS-X":
|
||||
traktAudioFormat = "dts_x";
|
||||
break;
|
||||
case "MP3":
|
||||
traktAudioFormat = "mp3";
|
||||
break;
|
||||
case "MP2":
|
||||
traktAudioFormat = "mp2";
|
||||
break;
|
||||
case "Vorbis":
|
||||
traktAudioFormat = "ogg";
|
||||
break;
|
||||
case "WMA":
|
||||
traktAudioFormat = "wma";
|
||||
break;
|
||||
case "AAC":
|
||||
traktAudioFormat = "aac";
|
||||
break;
|
||||
case "PCM":
|
||||
traktAudioFormat = "lpcm";
|
||||
break;
|
||||
case "FLAC":
|
||||
traktAudioFormat = "flac";
|
||||
break;
|
||||
case "Opus":
|
||||
traktAudioFormat = "ogg_opus";
|
||||
break;
|
||||
}
|
||||
"AC3" => "dolby_digital",
|
||||
"EAC3" => "dolby_digital_plus",
|
||||
"TrueHD" => "dolby_truehd",
|
||||
"EAC3 Atmos" => "dolby_digital_plus_atmos",
|
||||
"TrueHD Atmos" => "dolby_atmos",
|
||||
"DTS" => "dts",
|
||||
"DTS-ES" => "dts",
|
||||
"DTS-HD MA" => "dts_ma",
|
||||
"DTS-HD HRA" => "dts_hr",
|
||||
"DTS-X" => "dts_x",
|
||||
"MP3" => "mp3",
|
||||
"MP2" => "mp2",
|
||||
"Vorbis" => "ogg",
|
||||
"WMA" => "wma",
|
||||
"AAC" => "aac",
|
||||
"PCM" => "lpcm",
|
||||
"FLAC" => "flac",
|
||||
"Opus" => "ogg_opus",
|
||||
_ => string.Empty
|
||||
};
|
||||
|
||||
return traktAudioFormat;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,9 @@ namespace NzbDrone.Core.Notifications.Trakt
|
||||
{
|
||||
public static class TraktInterlacedTypes
|
||||
{
|
||||
private static HashSet<string> _interlacedTypes;
|
||||
|
||||
static TraktInterlacedTypes()
|
||||
public static readonly HashSet<string> InterlacedTypes = new (StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
_interlacedTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"Interlaced", "MBAFF", "PAFF"
|
||||
};
|
||||
}
|
||||
|
||||
public static HashSet<string> interlacedTypes => _interlacedTypes;
|
||||
"Interlaced", "MBAFF", "PAFF"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
@@ -76,6 +77,7 @@ namespace NzbDrone.Core.Notifications.Trakt
|
||||
{
|
||||
var request = new HttpRequestBuilder(RenewUri)
|
||||
.AddQueryParam("refresh_token", refreshToken)
|
||||
.WithRateLimit(2)
|
||||
.Build();
|
||||
|
||||
return _httpClient.Get<TraktAuthRefreshResource>(request)?.Resource ?? null;
|
||||
@@ -85,6 +87,7 @@ namespace NzbDrone.Core.Notifications.Trakt
|
||||
{
|
||||
var request = new HttpRequestBuilder(URL).Resource(resource).Build();
|
||||
|
||||
request.RateLimit = TimeSpan.FromSeconds(2);
|
||||
request.Headers.Accept = HttpAccept.Json.Value;
|
||||
request.Method = method;
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace NzbDrone.Core.Notifications.Twitter
|
||||
using (var reader = new StreamReader(responseStream))
|
||||
{
|
||||
var responseBody = reader.ReadToEnd();
|
||||
_logger.Trace("Reponse: {0} Status Code: {1}", responseBody, httpResponse.StatusCode);
|
||||
_logger.Trace("Response: {0} Status Code: {1}", responseBody, httpResponse.StatusCode);
|
||||
throw new TwitterException("Error received from Twitter: " + responseBody, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace NzbDrone.Core.Organizer
|
||||
new Dictionary<string, int>(FileNameBuilderTokenEqualityComparer.Instance)
|
||||
{
|
||||
{ MediaInfoVideoDynamicRangeToken, 5 },
|
||||
{ MediaInfoVideoDynamicRangeTypeToken, 10 }
|
||||
{ MediaInfoVideoDynamicRangeTypeToken, 11 }
|
||||
};
|
||||
|
||||
private void AddMediaInfoTokens(Dictionary<string, Func<TokenMatch, string>> tokenHandlers, MovieFile movieFile)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<PackageReference Include="Diacritical.Net" Version="1.0.4" />
|
||||
<PackageReference Include="Equ" Version="2.3.0" />
|
||||
<PackageReference Include="MailKit" Version="3.6.0" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.4" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.6" />
|
||||
<PackageReference Include="Servarr.FFMpegCore" Version="4.7.0-26" />
|
||||
<PackageReference Include="Servarr.FFprobe" Version="5.1.4.112" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
@@ -24,7 +24,7 @@
|
||||
<PackageReference Include="NLog" Version="5.2.3" />
|
||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.8" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.9" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Common\Radarr.Common.csproj" />
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.2" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.1" />
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
||||
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace NzbDrone.Host
|
||||
|
||||
case ApplicationModes.RegisterUrl:
|
||||
{
|
||||
_logger.Debug("Regiser URL selected");
|
||||
_logger.Debug("Register URL selected");
|
||||
_remoteAccessAdapter.MakeAccessible(false);
|
||||
_appFolderFactory.SetPermissions();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.21" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.25" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Test.Common\Radarr.Test.Common.csproj" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
The netstandard veresion here doesn't work in net framework
|
||||
The netstandard version here doesn't work in net framework
|
||||
See https://github.com/xamarin/XamarinComponents/issues/282
|
||||
-->
|
||||
<ItemGroup>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
The netstandard veresion here doesn't work in net framework
|
||||
The netstandard version here doesn't work in net framework
|
||||
See https://github.com/xamarin/XamarinComponents/issues/282
|
||||
-->
|
||||
<ItemGroup>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.1" />
|
||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
||||
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||
<PackageReference Include="NLog" Version="5.2.3" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1207,10 +1207,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||
|
||||
"@microsoft/signalr@6.0.21":
|
||||
version "6.0.21"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-6.0.21.tgz#b45f335df7011abba831cb3d7974b58da7e725c7"
|
||||
integrity sha512-3MWhSUE7AxkQs3QBuJ/spJJpg1mAHo0/6yRGhs5+Hew3Z+iqYrHVfo0yTElC7W2bVA9t3fW3jliQ9rBN0OvJLA==
|
||||
"@microsoft/signalr@6.0.25":
|
||||
version "6.0.25"
|
||||
resolved "https://registry.yarnpkg.com/@microsoft/signalr/-/signalr-6.0.25.tgz#009f043066d383e2de41a483bd7e02bfd74d3cf8"
|
||||
integrity sha512-8AzrpxS+E0yn1tXSlv7+UlURLmSxTQDgbvOT0pGKXjZT7MkhnDP+/GLuk7veRtUjczou/x32d9PHhYlr2NBy6Q==
|
||||
dependencies:
|
||||
abort-controller "^3.0.0"
|
||||
eventsource "^1.0.7"
|
||||
|
||||
Reference in New Issue
Block a user