mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2026-04-17 21:44:48 -04:00
Compare commits
41 Commits
v1.10.5.41
...
v1.11.3.41
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14f9a75a73 | ||
|
|
ed17d91a7b | ||
|
|
f54280b888 | ||
|
|
7890ef6f9d | ||
|
|
df8e4e5acb | ||
|
|
1b36951879 | ||
|
|
d8d5170ab8 | ||
|
|
a443a87603 | ||
|
|
df18ee77e7 | ||
|
|
426159b452 | ||
|
|
8704bef69a | ||
|
|
0f1b01adab | ||
|
|
4dbf5aa9f4 | ||
|
|
e1264d7cda | ||
|
|
d4bbb2e14a | ||
|
|
a2395dccb5 | ||
|
|
df89450428 | ||
|
|
7b5e1f40ba | ||
|
|
fe142b8a1c | ||
|
|
8c7f73ed16 | ||
|
|
a4ae800603 | ||
|
|
e5d7a21714 | ||
|
|
67355ec07b | ||
|
|
43d56f6817 | ||
|
|
515f4dff8b | ||
|
|
c3aa377ed5 | ||
|
|
fbc3c09094 | ||
|
|
b88f8e5fde | ||
|
|
aaf4c73c83 | ||
|
|
7c38ec2baa | ||
|
|
dcfdd49119 | ||
|
|
badb9dee61 | ||
|
|
12ca705556 | ||
|
|
a0d0e3e232 | ||
|
|
e12cd68772 | ||
|
|
9dc117191e | ||
|
|
fdaca64d60 | ||
|
|
6d134750ff | ||
|
|
bbf9945b49 | ||
|
|
b66a85269f | ||
|
|
81e9c29d54 |
@@ -9,7 +9,7 @@ variables:
|
||||
testsFolder: './_tests'
|
||||
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
|
||||
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
|
||||
majorVersion: '1.10.5'
|
||||
majorVersion: '1.11.3'
|
||||
minorVersion: $[counter('minorVersion', 1)]
|
||||
prowlarrVersion: '$(majorVersion).$(minorVersion)'
|
||||
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
|
||||
|
||||
13
frontend/src/Components/Form/InfoInput.css
Normal file
13
frontend/src/Components/Form/InfoInput.css
Normal file
@@ -0,0 +1,13 @@
|
||||
.message {
|
||||
composes: alert from '~Components/Alert.css';
|
||||
|
||||
a {
|
||||
color: var(--linkColor);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: var(--linkHoverColor);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
frontend/src/Components/Form/InfoInput.css.d.ts
vendored
Normal file
7
frontend/src/Components/Form/InfoInput.css.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'message': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import styles from './InfoInput.css';
|
||||
|
||||
class InfoInput extends Component {
|
||||
|
||||
@@ -12,7 +13,10 @@ class InfoInput extends Component {
|
||||
const { value } = this.props;
|
||||
|
||||
return (
|
||||
<Alert kind={kinds.INFO}>
|
||||
<Alert
|
||||
kind={kinds.INFO}
|
||||
className={styles.message}
|
||||
>
|
||||
<span dangerouslySetInnerHTML={{ __html: value }} />
|
||||
</Alert>
|
||||
);
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
"start_url": "../../../../",
|
||||
"theme_color": "#3a3f51",
|
||||
"background_color": "#3a3f51",
|
||||
"display": "standalone"
|
||||
"display": "minimal-ui"
|
||||
}
|
||||
|
||||
13
frontend/src/Search/Table/ReleaseLinks.css
Normal file
13
frontend/src/Search/Table/ReleaseLinks.css
Normal file
@@ -0,0 +1,13 @@
|
||||
.links {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.linkLabel {
|
||||
composes: label from '~Components/Label.css';
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
9
frontend/src/Search/Table/ReleaseLinks.css.d.ts
vendored
Normal file
9
frontend/src/Search/Table/ReleaseLinks.css.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'link': string;
|
||||
'linkLabel': string;
|
||||
'links': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
90
frontend/src/Search/Table/ReleaseLinks.tsx
Normal file
90
frontend/src/Search/Table/ReleaseLinks.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import React from 'react';
|
||||
import Label from 'Components/Label';
|
||||
import Link from 'Components/Link/Link';
|
||||
import { kinds, sizes } from 'Helpers/Props';
|
||||
import { IndexerCategory } from 'Indexer/Indexer';
|
||||
import styles from './ReleaseLinks.css';
|
||||
|
||||
interface ReleaseLinksProps {
|
||||
categories: IndexerCategory[];
|
||||
imdbId?: string;
|
||||
tmdbId?: number;
|
||||
tvdbId?: number;
|
||||
tvMazeId?: number;
|
||||
}
|
||||
|
||||
function ReleaseLinks(props: ReleaseLinksProps) {
|
||||
const { categories = [], imdbId, tmdbId, tvdbId, tvMazeId } = props;
|
||||
|
||||
const categoryNames = categories
|
||||
.filter((item) => item.id < 100000)
|
||||
.map((c) => c.name);
|
||||
|
||||
return (
|
||||
<div className={styles.links}>
|
||||
{imdbId ? (
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`https://imdb.com/title/tt${imdbId.toString().padStart(7, '0')}/`}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
IMDb
|
||||
</Label>
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
{tmdbId ? (
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`https://www.themoviedb.org/${
|
||||
categoryNames.includes('Movies') ? 'movie' : 'tv'
|
||||
}/${tmdbId}`}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
TMDb
|
||||
</Label>
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
{tvdbId ? (
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`https://www.thetvdb.com/?tab=series&id=${tvdbId}`}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
TVDb
|
||||
</Label>
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
{tvMazeId ? (
|
||||
<Link
|
||||
className={styles.link}
|
||||
to={`https://www.tvmaze.com/shows/${tvMazeId}/_`}
|
||||
>
|
||||
<Label
|
||||
className={styles.linkLabel}
|
||||
kind={kinds.INFO}
|
||||
size={sizes.LARGE}
|
||||
>
|
||||
TV Maze
|
||||
</Label>
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ReleaseLinks;
|
||||
@@ -63,7 +63,7 @@
|
||||
}
|
||||
|
||||
.externalLinks {
|
||||
margin: 0 2px;
|
||||
width: 22px;
|
||||
text-align: center;
|
||||
composes: button from '~Components/Link/IconButton.css';
|
||||
|
||||
color: var(--textColor);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import titleCase from 'Utilities/String/titleCase';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import CategoryLabel from './CategoryLabel';
|
||||
import Peers from './Peers';
|
||||
import ReleaseLinks from './ReleaseLinks';
|
||||
import styles from './SearchIndexRow.css';
|
||||
|
||||
function getDownloadIcon(isGrabbing, isGrabbed, grabError) {
|
||||
@@ -118,6 +119,10 @@ class SearchIndexRow extends Component {
|
||||
grabs,
|
||||
seeders,
|
||||
leechers,
|
||||
imdbId,
|
||||
tmdbId,
|
||||
tvdbId,
|
||||
tvMazeId,
|
||||
indexerFlags,
|
||||
columns,
|
||||
isGrabbing,
|
||||
@@ -343,6 +348,32 @@ class SearchIndexRow extends Component {
|
||||
/> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
imdbId || tmdbId || tvdbId || tvMazeId ? (
|
||||
<Popover
|
||||
anchor={
|
||||
<Icon
|
||||
className={styles.externalLinks}
|
||||
name={icons.EXTERNAL_LINK}
|
||||
size={12}
|
||||
/>
|
||||
}
|
||||
title={translate('Links')}
|
||||
body={
|
||||
<ReleaseLinks
|
||||
categories={categories}
|
||||
imdbId={imdbId}
|
||||
tmdbId={tmdbId}
|
||||
tvdbId={tvdbId}
|
||||
tvMazeId={tvMazeId}
|
||||
/>
|
||||
}
|
||||
kind={kinds.INVERSE}
|
||||
position={tooltipPositions.TOP}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
@@ -375,6 +406,10 @@ SearchIndexRow.propTypes = {
|
||||
grabs: PropTypes.number,
|
||||
seeders: PropTypes.number,
|
||||
leechers: PropTypes.number,
|
||||
imdbId: PropTypes.number,
|
||||
tmdbId: PropTypes.number,
|
||||
tvdbId: PropTypes.number,
|
||||
tvMazeId: PropTypes.number,
|
||||
indexerFlags: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onGrabPress: PropTypes.func.isRequired,
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Test.IndexerTests.OrpheusTests
|
||||
|
||||
var torrentInfo = releases.First() as TorrentInfo;
|
||||
|
||||
torrentInfo.Title.Should().Be("The Beatles - Abbey Road [1969] [Album] [2.0 Mix 2019] [MP3 V2 (VBR)] [BD]");
|
||||
torrentInfo.Title.Should().Be("The Beatles - Abbey Road (1969) [Album] [2.0 Mix 2019] [MP3 V2 (VBR) / BD]");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("https://orpheus.network/ajax.php?action=download&id=1902448");
|
||||
torrentInfo.InfoUrl.Should().Be("https://orpheus.network/torrents.php?id=466&torrentid=1902448");
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace NzbDrone.Core.Test.IndexerTests.RedactedTests
|
||||
|
||||
var torrentInfo = releases.First() as TorrentInfo;
|
||||
|
||||
torrentInfo.Title.Should().Be("Red Hot Chili Peppers - Californication [1999] [Album] [US / Reissue 2020] [FLAC 24bit Lossless] [Vinyl]");
|
||||
torrentInfo.Title.Should().Be("Red Hot Chili Peppers - Californication (1999) [Album] [US / Reissue 2020] [FLAC 24bit Lossless / Vinyl]");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("https://redacted.ch/ajax.php?action=download&id=3892313");
|
||||
torrentInfo.InfoUrl.Should().Be("https://redacted.ch/torrents.php?id=16720&torrentid=3892313");
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="NBuilder" Version="6.1.0" />
|
||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||
<PackageReference Include="YamlDotNet" Version="13.7.1" />
|
||||
<PackageReference Include="YamlDotNet" Version="13.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NzbDrone.Test.Common\Prowlarr.Test.Common.csproj" />
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AngleSharp.Html.Parser;
|
||||
using NLog;
|
||||
@@ -10,6 +11,7 @@ using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions;
|
||||
|
||||
[Obsolete("Site has shutdown")]
|
||||
public class AroLol : GazelleBase<AroLolSettings>
|
||||
{
|
||||
public override string Name => "aro.lol";
|
||||
|
||||
@@ -7,6 +7,7 @@ using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Indexers.Exceptions;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions.Avistaz
|
||||
@@ -15,9 +16,9 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
|
||||
{
|
||||
public override bool SupportsRss => true;
|
||||
public override bool SupportsSearch => true;
|
||||
public override bool SupportsPagination => true;
|
||||
public override bool SupportsPagination => false;
|
||||
public override int PageSize => 50;
|
||||
public override TimeSpan RateLimit => TimeSpan.FromSeconds(5);
|
||||
public override TimeSpan RateLimit => TimeSpan.FromSeconds(6);
|
||||
public override IndexerCapabilities Capabilities => SetCapabilities();
|
||||
protected virtual string LoginUrl => Settings.BaseUrl + "api/v1/jackett/auth";
|
||||
private IIndexerRepository _indexerRepository;
|
||||
@@ -50,21 +51,28 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
|
||||
return new AvistazParserBase();
|
||||
}
|
||||
|
||||
protected virtual IndexerCapabilities SetCapabilities()
|
||||
{
|
||||
return new IndexerCapabilities();
|
||||
}
|
||||
protected abstract IndexerCapabilities SetCapabilities();
|
||||
|
||||
protected override async Task DoLogin()
|
||||
{
|
||||
Settings.Token = await GetToken();
|
||||
|
||||
if (Definition.Id > 0)
|
||||
try
|
||||
{
|
||||
_indexerRepository.UpdateSettings((IndexerDefinition)Definition);
|
||||
}
|
||||
Settings.Token = await GetToken();
|
||||
|
||||
_logger.Debug("Avistaz authentication succeeded.");
|
||||
if (Definition.Id > 0)
|
||||
{
|
||||
_indexerRepository.UpdateSettings((IndexerDefinition)Definition);
|
||||
}
|
||||
|
||||
_logger.Debug("Avistaz authentication succeeded.");
|
||||
}
|
||||
catch (HttpException ex) when (ex.Response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
_logger.Warn(ex, "Failed to authenticate with Avistaz");
|
||||
|
||||
var jsonResponse = STJson.Deserialize<AvistazErrorResponse>(ex.Response.Content);
|
||||
throw new IndexerAuthException(jsonResponse?.Message ?? "Unauthorized request to indexer");
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
|
||||
@@ -116,11 +124,12 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
|
||||
Method = HttpMethod.Post
|
||||
};
|
||||
|
||||
// TODO: Change to HttpAccept.Json after they fix the issue with missing headers
|
||||
var authLoginRequest = requestBuilder
|
||||
.AddFormParameter("username", Settings.Username)
|
||||
.AddFormParameter("password", Settings.Password)
|
||||
.AddFormParameter("pid", Settings.Pid.Trim())
|
||||
.Accept(HttpAccept.Json)
|
||||
.Accept(HttpAccept.Html)
|
||||
.Build();
|
||||
|
||||
var response = await ExecuteAuth(authLoginRequest);
|
||||
|
||||
@@ -69,11 +69,22 @@ namespace NzbDrone.Core.Indexers.Definitions.Avistaz
|
||||
DownloadVolumeFactor = row.DownloadMultiply,
|
||||
UploadVolumeFactor = row.UploadMultiply,
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 172800, // 48 hours
|
||||
MinimumSeedTime = 259200, // 72 hours
|
||||
Languages = row.Audio?.Select(x => x.Language).ToList() ?? new List<string>(),
|
||||
Subs = row.Subtitle?.Select(x => x.Language).ToList() ?? new List<string>()
|
||||
};
|
||||
|
||||
if (row.FileSize is > 0)
|
||||
{
|
||||
var sizeGigabytes = row.FileSize.Value / Math.Pow(1024, 3);
|
||||
|
||||
release.MinimumSeedTime = sizeGigabytes switch
|
||||
{
|
||||
> 50.0 => (long)((100 * Math.Log(sizeGigabytes)) - 219.2023) * 3600,
|
||||
_ => 259200 + (long)(sizeGigabytes * 7200)
|
||||
};
|
||||
}
|
||||
|
||||
if (row.MovieTvinfo != null)
|
||||
{
|
||||
release.ImdbId = ParseUtil.GetImdbId(row.MovieTvinfo.Imdb).GetValueOrDefault();
|
||||
|
||||
@@ -48,6 +48,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
return new BeyondHDParser(Capabilities.Categories);
|
||||
}
|
||||
|
||||
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
|
||||
|
||||
return FilterReleasesByQuery(cleanReleases, searchCriteria).ToList();
|
||||
}
|
||||
|
||||
private IndexerCapabilities SetCapabilities()
|
||||
{
|
||||
var caps = new IndexerCapabilities
|
||||
|
||||
@@ -9,7 +9,9 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
public class BroadcastheNet : TorrentIndexerBase<BroadcastheNetSettings>
|
||||
{
|
||||
public override string Name => "BroadcasTheNet";
|
||||
|
||||
public override string[] IndexerUrls => new[] { "https://api.broadcasthe.net/" };
|
||||
public override string[] LegacyUrls => new[] { "http://api.broadcasthe.net/" };
|
||||
public override string Description => "BroadcasTheNet (BTN) is an invite-only torrent tracker focused on TV shows";
|
||||
public override IndexerPrivacy Privacy => IndexerPrivacy.Private;
|
||||
public override bool SupportsRss => true;
|
||||
public override bool SupportsSearch => true;
|
||||
@@ -18,11 +20,6 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
public override IndexerCapabilities Capabilities => SetCapabilities();
|
||||
public override TimeSpan RateLimit => TimeSpan.FromSeconds(5);
|
||||
|
||||
public override string[] IndexerUrls => new string[] { "https://api.broadcasthe.net/" };
|
||||
public override string[] LegacyUrls => new string[] { "http://api.broadcasthe.net/" };
|
||||
|
||||
public override string Description => "BroadcasTheNet (BTN) is an invite-only torrent tracker focused on TV shows";
|
||||
|
||||
public BroadcastheNet(IIndexerHttpClient httpClient, IEventAggregator eventAggregator, IIndexerStatusService indexerStatusService, IConfigService configService, Logger logger)
|
||||
: base(httpClient, eventAggregator, indexerStatusService, configService, logger)
|
||||
{
|
||||
@@ -30,18 +27,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
|
||||
public override IIndexerRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
var requestGenerator = new BroadcastheNetRequestGenerator() { Settings = Settings, PageSize = PageSize, Capabilities = Capabilities };
|
||||
|
||||
var releaseInfo = _indexerStatusService.GetLastRssSyncReleaseInfo(Definition.Id);
|
||||
if (releaseInfo != null)
|
||||
{
|
||||
if (int.TryParse(releaseInfo.Guid.Replace("BTN-", string.Empty), out var torrentId))
|
||||
{
|
||||
requestGenerator.LastRecentTorrentID = torrentId;
|
||||
}
|
||||
}
|
||||
|
||||
return requestGenerator;
|
||||
return new BroadcastheNetRequestGenerator { Settings = Settings, Capabilities = Capabilities, PageSize = PageSize };
|
||||
}
|
||||
|
||||
public override IParseIndexerResponse GetParser()
|
||||
@@ -65,7 +51,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
caps.Categories.AddCategoryMapping("720p", NewznabStandardCategory.TVHD, "720p");
|
||||
caps.Categories.AddCategoryMapping("1080p", NewznabStandardCategory.TVHD, "1080p");
|
||||
caps.Categories.AddCategoryMapping("1080i", NewznabStandardCategory.TVHD, "1080i");
|
||||
caps.Categories.AddCategoryMapping("2160p", NewznabStandardCategory.TVHD, "2160p");
|
||||
caps.Categories.AddCategoryMapping("2160p", NewznabStandardCategory.TVUHD, "2160p");
|
||||
caps.Categories.AddCategoryMapping("Portable Device", NewznabStandardCategory.TVSD, "Portable Device");
|
||||
|
||||
return caps;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
|
||||
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
|
||||
{
|
||||
var results = new List<ReleaseInfo>();
|
||||
var releaseInfos = new List<ReleaseInfo>();
|
||||
var indexerHttpResponse = indexerResponse.HttpResponse;
|
||||
|
||||
switch (indexerHttpResponse.StatusCode)
|
||||
@@ -69,67 +69,76 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
|
||||
if (jsonResponse.Result.Results == 0 || jsonResponse.Result?.Torrents?.Values == null)
|
||||
{
|
||||
return results;
|
||||
return releaseInfos;
|
||||
}
|
||||
|
||||
var protocol = indexerResponse.HttpRequest.Url.Scheme + ":";
|
||||
|
||||
foreach (var torrent in jsonResponse.Result.Torrents.Values)
|
||||
{
|
||||
var torrentInfo = new TorrentInfo();
|
||||
var flags = new HashSet<IndexerFlag>();
|
||||
|
||||
torrentInfo.Guid = string.Format("BTN-{0}", torrent.TorrentID);
|
||||
torrentInfo.Title = CleanReleaseName(torrent.ReleaseName);
|
||||
torrentInfo.Size = torrent.Size;
|
||||
torrentInfo.DownloadUrl = RegexProtocol.Replace(torrent.DownloadURL, protocol);
|
||||
torrentInfo.InfoUrl = string.Format("{0}//broadcasthe.net/torrents.php?id={1}&torrentid={2}", protocol, torrent.GroupID, torrent.TorrentID);
|
||||
|
||||
//torrentInfo.CommentUrl =
|
||||
if (torrent.TvdbID.HasValue)
|
||||
if (torrent.Origin.ToUpperInvariant() == "INTERNAL")
|
||||
{
|
||||
torrentInfo.TvdbId = torrent.TvdbID.Value;
|
||||
flags.Add(IndexerFlag.Internal);
|
||||
}
|
||||
|
||||
if (torrent.TvrageID.HasValue)
|
||||
var releaseInfo = new TorrentInfo
|
||||
{
|
||||
torrentInfo.TvRageId = torrent.TvrageID.Value;
|
||||
Guid = $"BTN-{torrent.TorrentID}",
|
||||
InfoUrl = $"{protocol}//broadcasthe.net/torrents.php?id={torrent.GroupID}&torrentid={torrent.TorrentID}",
|
||||
DownloadUrl = RegexProtocol.Replace(torrent.DownloadURL, protocol),
|
||||
Title = CleanReleaseName(torrent.ReleaseName),
|
||||
Categories = _categories.MapTrackerCatToNewznab(torrent.Resolution),
|
||||
InfoHash = torrent.InfoHash,
|
||||
Size = torrent.Size,
|
||||
Grabs = torrent.Snatched,
|
||||
Seeders = torrent.Seeders,
|
||||
Peers = torrent.Leechers + torrent.Seeders,
|
||||
PublishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime().AddSeconds(torrent.Time),
|
||||
Origin = torrent.Origin,
|
||||
Source = torrent.Source,
|
||||
Container = torrent.Container,
|
||||
Codec = torrent.Codec,
|
||||
Resolution = torrent.Resolution,
|
||||
Scene = torrent.Origin.ToUpperInvariant() == "SCENE",
|
||||
IndexerFlags = flags,
|
||||
DownloadVolumeFactor = 0,
|
||||
UploadVolumeFactor = 1,
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = torrent.Category.ToUpperInvariant() == "SEASON" ? 432000 : 86400, // 120 hours for seasons and 24 hours for episodes
|
||||
};
|
||||
|
||||
if (torrent.TvdbID is > 0)
|
||||
{
|
||||
releaseInfo.TvdbId = torrent.TvdbID.Value;
|
||||
}
|
||||
|
||||
torrentInfo.PublishDate = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).ToUniversalTime().AddSeconds(torrent.Time);
|
||||
if (torrent.TvrageID is > 0)
|
||||
{
|
||||
releaseInfo.TvRageId = torrent.TvrageID.Value;
|
||||
}
|
||||
|
||||
//torrentInfo.MagnetUrl =
|
||||
torrentInfo.InfoHash = torrent.InfoHash;
|
||||
torrentInfo.Seeders = torrent.Seeders;
|
||||
torrentInfo.Peers = torrent.Leechers + torrent.Seeders;
|
||||
|
||||
torrentInfo.Origin = torrent.Origin;
|
||||
torrentInfo.Source = torrent.Source;
|
||||
torrentInfo.Container = torrent.Container;
|
||||
torrentInfo.Codec = torrent.Codec;
|
||||
torrentInfo.Resolution = torrent.Resolution;
|
||||
torrentInfo.UploadVolumeFactor = 1;
|
||||
torrentInfo.DownloadVolumeFactor = 0;
|
||||
torrentInfo.MinimumRatio = 1;
|
||||
|
||||
torrentInfo.Categories = _categories.MapTrackerCatToNewznab(torrent.Resolution);
|
||||
if (torrent.ImdbID.IsNotNullOrWhiteSpace() && int.TryParse(torrent.ImdbID, out var imdbId))
|
||||
{
|
||||
releaseInfo.ImdbId = imdbId;
|
||||
}
|
||||
|
||||
// Default to TV if category could not be mapped
|
||||
if (torrentInfo.Categories == null || !torrentInfo.Categories.Any())
|
||||
if (releaseInfo.Categories == null || !releaseInfo.Categories.Any())
|
||||
{
|
||||
torrentInfo.Categories = new List<IndexerCategory> { NewznabStandardCategory.TV };
|
||||
releaseInfo.Categories = new List<IndexerCategory> { NewznabStandardCategory.TV };
|
||||
}
|
||||
|
||||
results.Add(torrentInfo);
|
||||
releaseInfos.Add(releaseInfo);
|
||||
}
|
||||
|
||||
return results;
|
||||
return releaseInfos;
|
||||
}
|
||||
|
||||
private string CleanReleaseName(string releaseName)
|
||||
{
|
||||
releaseName = releaseName.Replace("\\", "");
|
||||
|
||||
return releaseName;
|
||||
return releaseName.Replace("\\", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,31 +9,13 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
{
|
||||
public class BroadcastheNetRequestGenerator : IIndexerRequestGenerator
|
||||
{
|
||||
public int MaxPages { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
public BroadcastheNetSettings Settings { get; set; }
|
||||
public IndexerCapabilities Capabilities { get; set; }
|
||||
|
||||
public int? LastRecentTorrentID { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
|
||||
public Func<IDictionary<string, string>> GetCookies { get; set; }
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
|
||||
public BroadcastheNetRequestGenerator()
|
||||
{
|
||||
MaxPages = 10;
|
||||
PageSize = 100;
|
||||
}
|
||||
|
||||
private IEnumerable<IndexerRequest> GetPagedRequests(BroadcastheNetTorrentQuery parameters, int results, int offset)
|
||||
{
|
||||
var builder = new JsonRpcRequestBuilder(Settings.BaseUrl)
|
||||
.Call("getTorrents", Settings.ApiKey, parameters, results, offset);
|
||||
builder.SuppressHttpError = true;
|
||||
|
||||
yield return new IndexerRequest(builder.Build());
|
||||
}
|
||||
|
||||
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
|
||||
{
|
||||
return new IndexerPageableRequestChain();
|
||||
@@ -132,11 +114,24 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
|
||||
var btnOffset = searchCriteria.Offset.GetValueOrDefault(0);
|
||||
|
||||
parameters.Search = searchString.Replace(" ", "%");
|
||||
if (searchString.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
parameters.Search = searchString.Replace(" ", "%");
|
||||
}
|
||||
|
||||
pageableRequests.Add(GetPagedRequests(parameters, btnResults, btnOffset));
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<IndexerRequest> GetPagedRequests(BroadcastheNetTorrentQuery parameters, int results, int offset)
|
||||
{
|
||||
var builder = new JsonRpcRequestBuilder(Settings.BaseUrl)
|
||||
.Call("getTorrents", Settings.ApiKey, parameters, results, offset);
|
||||
|
||||
builder.SuppressHttpError = true;
|
||||
|
||||
yield return new IndexerRequest(builder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
{
|
||||
@@ -13,15 +14,15 @@ namespace NzbDrone.Core.Indexers.BroadcastheNet
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Search { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Codec { get; set; }
|
||||
public IEnumerable<string> Codec { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Container { get; set; }
|
||||
public IEnumerable<string> Container { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Source { get; set; }
|
||||
public IEnumerable<string> Source { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Resolution { get; set; }
|
||||
public IEnumerable<string> Resolution { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Origin { get; set; }
|
||||
public IEnumerable<string> Origin { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public string Hash { get; set; }
|
||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions.FileList;
|
||||
|
||||
@@ -40,6 +43,13 @@ public class FileList : TorrentIndexerBase<FileListSettings>
|
||||
return new FileListParser(Settings, Capabilities.Categories);
|
||||
}
|
||||
|
||||
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
|
||||
|
||||
return FilterReleasesByQuery(cleanReleases, searchCriteria).ToList();
|
||||
}
|
||||
|
||||
private IndexerCapabilities SetCapabilities()
|
||||
{
|
||||
var caps = new IndexerCapabilities
|
||||
|
||||
@@ -73,6 +73,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
return CookieUtil.CookieHeaderToDictionary(Settings.Cookie);
|
||||
}
|
||||
|
||||
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
|
||||
|
||||
return FilterReleasesByQuery(cleanReleases, searchCriteria).ToList();
|
||||
}
|
||||
|
||||
private IndexerCapabilities SetCapabilities()
|
||||
{
|
||||
var caps = new IndexerCapabilities
|
||||
@@ -293,6 +300,10 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
var parser = new HtmlParser();
|
||||
using var doc = parser.ParseDocument(indexerResponse.Content);
|
||||
|
||||
var headerColumns = doc.QuerySelectorAll("table[id=\"torrents\"] > thead > tr > th").Select(x => x.TextContent.Trim()).ToList();
|
||||
var sizeIndex = FindColumnIndexOrDefault(headerColumns, "Sort by size", 5);
|
||||
var filesIndex = FindColumnIndexOrDefault(headerColumns, "Sort by files");
|
||||
|
||||
var rows = doc.QuerySelectorAll("table[id=\"torrents\"] > tbody > tr");
|
||||
foreach (var row in rows)
|
||||
{
|
||||
@@ -314,7 +325,6 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
var dateSplit = descrSplit.Last().Split(new[] { " by " }, StringSplitOptions.None);
|
||||
var publishDate = DateTimeUtil.FromTimeAgo(dateSplit.First());
|
||||
var description = descrSplit.Length > 1 ? "Tags: " + descrSplit.First().Trim() : "";
|
||||
description += dateSplit.Length > 1 ? " Uploaded by: " + dateSplit.Last().Trim() : "";
|
||||
|
||||
var catIcon = row.QuerySelector("td:nth-of-type(1) a");
|
||||
if (catIcon == null)
|
||||
@@ -327,36 +337,40 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
// Torrents - Category column == Icons
|
||||
var cat = _categories.MapTrackerCatToNewznab(catIcon.GetAttribute("href").Substring(1));
|
||||
|
||||
var size = ParseUtil.GetBytes(row.Children[5].TextContent);
|
||||
var size = ParseUtil.GetBytes(row.Children[sizeIndex].TextContent);
|
||||
|
||||
var colIndex = 6;
|
||||
int? files = null;
|
||||
|
||||
if (row.Children.Length == 10)
|
||||
if (filesIndex != -1)
|
||||
{
|
||||
files = ParseUtil.CoerceInt(row.Children[colIndex].TextContent.Replace("Go to files", ""));
|
||||
colIndex++;
|
||||
files = ParseUtil.CoerceInt(row.Children[filesIndex].TextContent.Replace("Go to files", ""));
|
||||
}
|
||||
|
||||
var grabs = ParseUtil.CoerceInt(row.Children[colIndex++].TextContent);
|
||||
var seeders = ParseUtil.CoerceInt(row.Children[colIndex++].TextContent);
|
||||
var leechers = ParseUtil.CoerceInt(row.Children[colIndex].TextContent);
|
||||
var dlVolumeFactor = row.QuerySelector("span.free") != null ? 0 : 1;
|
||||
var colIndex = row.Children.Length == 10 ? 7 : 6;
|
||||
|
||||
var grabsIndex = FindColumnIndexOrDefault(headerColumns, "Sort by snatches", colIndex++);
|
||||
var seedersIndex = FindColumnIndexOrDefault(headerColumns, "Sort by seeders", colIndex++);
|
||||
var leechersIndex = FindColumnIndexOrDefault(headerColumns, "Sort by leechers", colIndex);
|
||||
|
||||
var grabs = ParseUtil.CoerceInt(row.Children[grabsIndex].TextContent);
|
||||
var seeders = ParseUtil.CoerceInt(row.Children[seedersIndex].TextContent);
|
||||
var leechers = ParseUtil.CoerceInt(row.Children[leechersIndex].TextContent);
|
||||
|
||||
var release = new TorrentInfo
|
||||
{
|
||||
Title = title,
|
||||
Guid = details.AbsoluteUri,
|
||||
DownloadUrl = link.AbsoluteUri,
|
||||
InfoUrl = details.AbsoluteUri,
|
||||
PublishDate = publishDate,
|
||||
Title = title,
|
||||
Description = description,
|
||||
Categories = cat,
|
||||
Size = size,
|
||||
Files = files,
|
||||
Grabs = grabs,
|
||||
Seeders = seeders,
|
||||
Peers = seeders + leechers,
|
||||
DownloadVolumeFactor = dlVolumeFactor,
|
||||
PublishDate = publishDate,
|
||||
DownloadVolumeFactor = row.QuerySelector("span.free") != null ? 0 : 1,
|
||||
UploadVolumeFactor = 1,
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 1209600 // 336 hours
|
||||
@@ -368,6 +382,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
return torrentInfos.ToArray();
|
||||
}
|
||||
|
||||
private static int FindColumnIndexOrDefault(List<string> columns, string name, int defaultIndex = -1)
|
||||
{
|
||||
var index = columns.FindIndex(x => x.Equals(name, StringComparison.Ordinal));
|
||||
|
||||
return index != -1 ? index : defaultIndex;
|
||||
}
|
||||
|
||||
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
|
||||
|
||||
private static string CleanTitle(string title)
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Dom;
|
||||
@@ -76,12 +75,16 @@ public class NorBits : TorrentIndexerBase<NorBitsSettings>
|
||||
{
|
||||
LogResponseContent = true,
|
||||
AllowAutoRedirect = true,
|
||||
Method = HttpMethod.Post
|
||||
SuppressHttpError = true
|
||||
};
|
||||
|
||||
var authLoginCheckRequest = requestBuilder3
|
||||
.Post()
|
||||
.AddFormParameter("username", Settings.Username)
|
||||
.AddFormParameter("password", Settings.Password)
|
||||
.AddFormParameter("code", Settings.TwoFactorAuthCode ?? string.Empty)
|
||||
.AddFormParameter("logout", "no")
|
||||
.AddFormParameter("returnto", "/")
|
||||
.SetCookies(indexPage.GetCookies())
|
||||
.SetHeader("Referer", loginUrl)
|
||||
.Build();
|
||||
@@ -174,6 +177,11 @@ public class NorBitsRequestGenerator : IIndexerRequestGenerator
|
||||
{ "scenerelease", "0" }
|
||||
};
|
||||
|
||||
if (_settings.FreeLeechOnly)
|
||||
{
|
||||
parameters.Set("FL", "1");
|
||||
}
|
||||
|
||||
var searchTerm = "search=";
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(imdbId))
|
||||
@@ -343,6 +351,12 @@ public class NorBitsSettings : UserPassTorrentBaseSettings
|
||||
UseFullSearch = false;
|
||||
}
|
||||
|
||||
[FieldDefinition(4, Label = "Use Full Search", HelpText = "Use Full Search from Site", Type = FieldType.Checkbox)]
|
||||
[FieldDefinition(4, Label = "2FA code", Type = FieldType.Textbox, HelpText = "Only fill in the <b>2FA code</b> box if you have enabled <b>2FA</b> on the NorBits Web Site. Otherwise just leave it empty.")]
|
||||
public string TwoFactorAuthCode { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Use Full Search", Type = FieldType.Checkbox, HelpText = "Use Full Search from Site")]
|
||||
public bool UseFullSearch { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "FreeLeech Only", Type = FieldType.Checkbox, HelpText = "Search FreeLeech torrents only")]
|
||||
public bool FreeLeechOnly { get; set; }
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
private string GetTitle(GazelleRelease result, GazelleTorrent torrent)
|
||||
{
|
||||
var title = $"{result.Artist} - {result.GroupName} [{result.GroupYear}]";
|
||||
var title = $"{result.Artist} - {result.GroupName} ({result.GroupYear})";
|
||||
|
||||
if (result.ReleaseType.IsNotNullOrWhiteSpace() && result.ReleaseType != "Unknown")
|
||||
{
|
||||
@@ -374,14 +374,23 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
title += $" [{$"{torrent.RemasterTitle} {torrent.RemasterYear}".Trim()}]";
|
||||
}
|
||||
|
||||
title += $" [{torrent.Format} {torrent.Encoding}] [{torrent.Media}]";
|
||||
var flags = new List<string>
|
||||
{
|
||||
$"{torrent.Format} {torrent.Encoding}",
|
||||
$"{torrent.Media}"
|
||||
};
|
||||
|
||||
if (torrent.HasLog)
|
||||
{
|
||||
flags.Add("Log (" + torrent.LogScore + "%)");
|
||||
}
|
||||
|
||||
if (torrent.HasCue)
|
||||
{
|
||||
title += " [Cue]";
|
||||
flags.Add("Cue");
|
||||
}
|
||||
|
||||
return title;
|
||||
return $"{title} [{string.Join(" / ", flags)}]";
|
||||
}
|
||||
|
||||
private string GetDownloadUrl(int torrentId, bool canUseToken)
|
||||
@@ -392,7 +401,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
.AddQueryParam("id", torrentId);
|
||||
|
||||
// Orpheus fails to download if usetoken=0 so we need to only add if we will use one
|
||||
if (_settings.UseFreeleechToken)
|
||||
if (_settings.UseFreeleechToken && canUseToken)
|
||||
{
|
||||
url = url.AddQueryParam("usetoken", "1");
|
||||
}
|
||||
|
||||
@@ -94,7 +94,12 @@ namespace NzbDrone.Core.Indexers.Definitions.PassThePopcorn
|
||||
ImdbId = result.ImdbId.IsNotNullOrWhiteSpace() ? int.Parse(result.ImdbId) : 0,
|
||||
Scene = torrent.Scene,
|
||||
IndexerFlags = flags,
|
||||
DownloadVolumeFactor = torrent.FreeleechType is "Freeleech" ? 0 : 1,
|
||||
DownloadVolumeFactor = torrent.FreeleechType?.ToUpperInvariant() switch
|
||||
{
|
||||
"FREELEECH" => 0,
|
||||
"HALF LEECH" => 0.5,
|
||||
_ => 1
|
||||
},
|
||||
UploadVolumeFactor = 1,
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 345600,
|
||||
|
||||
@@ -193,6 +193,11 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
queryCats.ForEach(cat => parameters.Set($"filter_cat[{cat}]", "1"));
|
||||
}
|
||||
|
||||
if (_settings.FreeloadOnly)
|
||||
{
|
||||
parameters.Set("freetorrent", "4");
|
||||
}
|
||||
|
||||
var searchUrl = _settings.BaseUrl.TrimEnd('/') + $"/ajax.php?{parameters.GetQueryString()}";
|
||||
|
||||
var request = new IndexerRequest(searchUrl, HttpAccept.Json);
|
||||
@@ -242,6 +247,12 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
foreach (var torrent in result.Torrents)
|
||||
{
|
||||
// skip non-freeload results when freeload only is set
|
||||
if (_settings.FreeloadOnly && !torrent.IsFreeload)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var id = torrent.TorrentId;
|
||||
|
||||
var title = GetTitle(result, torrent);
|
||||
@@ -251,7 +262,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
Guid = infoUrl,
|
||||
InfoUrl = infoUrl,
|
||||
DownloadUrl = GetDownloadUrl(id, torrent.CanUseToken),
|
||||
DownloadUrl = GetDownloadUrl(id, torrent.CanUseToken && !torrent.IsFreeload),
|
||||
Title = WebUtility.HtmlDecode(title),
|
||||
Artist = WebUtility.HtmlDecode(result.Artist),
|
||||
Album = WebUtility.HtmlDecode(result.GroupName),
|
||||
@@ -286,6 +297,12 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
// Non-Audio files are formatted a little differently (1:1 for group and torrents)
|
||||
else
|
||||
{
|
||||
// skip non-freeload results when freeload only is set
|
||||
if (_settings.FreeloadOnly && !result.IsFreeload)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var id = result.TorrentId;
|
||||
var infoUrl = GetInfoUrl(result.GroupId, id);
|
||||
|
||||
@@ -294,7 +311,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
Guid = infoUrl,
|
||||
Title = WebUtility.HtmlDecode(result.GroupName),
|
||||
Size = long.Parse(result.Size),
|
||||
DownloadUrl = GetDownloadUrl(id, result.CanUseToken),
|
||||
DownloadUrl = GetDownloadUrl(id, result.CanUseToken && !result.IsFreeload),
|
||||
InfoUrl = infoUrl,
|
||||
Seeders = int.Parse(result.Seeders),
|
||||
Peers = int.Parse(result.Leechers) + int.Parse(result.Seeders),
|
||||
@@ -328,7 +345,7 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
private string GetTitle(GazelleRelease result, GazelleTorrent torrent)
|
||||
{
|
||||
var title = $"{result.Artist} - {result.GroupName} [{result.GroupYear}]";
|
||||
var title = $"{result.Artist} - {result.GroupName} ({result.GroupYear})";
|
||||
|
||||
if (result.ReleaseType.IsNotNullOrWhiteSpace() && result.ReleaseType != "Unknown")
|
||||
{
|
||||
@@ -340,14 +357,23 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
title += $" [{$"{torrent.RemasterTitle} {torrent.RemasterYear}".Trim()}]";
|
||||
}
|
||||
|
||||
title += $" [{torrent.Format} {torrent.Encoding}] [{torrent.Media}]";
|
||||
var flags = new List<string>
|
||||
{
|
||||
$"{torrent.Format} {torrent.Encoding}",
|
||||
$"{torrent.Media}"
|
||||
};
|
||||
|
||||
if (torrent.HasLog)
|
||||
{
|
||||
flags.Add("Log (" + torrent.LogScore + "%)");
|
||||
}
|
||||
|
||||
if (torrent.HasCue)
|
||||
{
|
||||
title += " [Cue]";
|
||||
flags.Add("Cue");
|
||||
}
|
||||
|
||||
return title;
|
||||
return $"{title} [{string.Join(" / ", flags)}]";
|
||||
}
|
||||
|
||||
private string GetDownloadUrl(int torrentId, bool canUseToken)
|
||||
@@ -394,12 +420,15 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
UseFreeleechToken = false;
|
||||
}
|
||||
|
||||
[FieldDefinition(2, Label = "API Key", HelpText = "API Key from the Site (Found in Settings => Access Settings)", Privacy = PrivacyLevel.ApiKey)]
|
||||
[FieldDefinition(2, Label = "API Key", Privacy = PrivacyLevel.ApiKey, HelpText = "API Key from the Site (Found in Settings => Access Settings)")]
|
||||
public string Apikey { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Use Freeleech Tokens", HelpText = "Use freeleech tokens when available", Type = FieldType.Checkbox)]
|
||||
[FieldDefinition(3, Label = "Use Freeleech Tokens", Type = FieldType.Checkbox, HelpText = "Use freeleech tokens when available")]
|
||||
public bool UseFreeleechToken { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Freeload Only", Type = FieldType.Checkbox, Advanced = true, HelpTextWarning = "Search freeload torrents only. End date: 6 January 2024, 23:59 UTC.")]
|
||||
public bool FreeloadOnly { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
@@ -22,13 +19,6 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
{
|
||||
}
|
||||
|
||||
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
|
||||
|
||||
return FilterReleasesByQuery(cleanReleases, searchCriteria).ToList();
|
||||
}
|
||||
|
||||
protected override IndexerCapabilities SetCapabilities()
|
||||
{
|
||||
var caps = new IndexerCapabilities
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -51,6 +50,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
return new SpeedAppParser(Settings, Capabilities.Categories, MinimumSeedTime);
|
||||
}
|
||||
|
||||
protected override IList<ReleaseInfo> CleanupReleases(IEnumerable<ReleaseInfo> releases, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var cleanReleases = base.CleanupReleases(releases, searchCriteria);
|
||||
|
||||
return FilterReleasesByQuery(cleanReleases, searchCriteria).ToList();
|
||||
}
|
||||
|
||||
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse)
|
||||
{
|
||||
return Settings.ApiKey.IsNullOrWhiteSpace() || httpResponse.StatusCode == HttpStatusCode.Unauthorized;
|
||||
@@ -58,14 +64,13 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
|
||||
protected override async Task DoLogin()
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(LoginUrl)
|
||||
{
|
||||
LogResponseContent = true,
|
||||
AllowAutoRedirect = true,
|
||||
Method = HttpMethod.Post,
|
||||
};
|
||||
|
||||
var request = requestBuilder.Build();
|
||||
var request = new HttpRequestBuilder(LoginUrl)
|
||||
{
|
||||
LogResponseContent = true,
|
||||
AllowAutoRedirect = true
|
||||
}
|
||||
.Post()
|
||||
.Build();
|
||||
|
||||
var data = new SpeedAppAuthenticationRequest
|
||||
{
|
||||
|
||||
@@ -110,7 +110,8 @@ namespace NzbDrone.Core.Indexers.Definitions
|
||||
BookSearchParams = new List<BookSearchParam>
|
||||
{
|
||||
BookSearchParam.Q
|
||||
}
|
||||
},
|
||||
SupportsRawSearch = true
|
||||
};
|
||||
|
||||
caps.Categories.AddCategoryMapping("117", NewznabStandardCategory.Movies, "Українське кіно");
|
||||
|
||||
@@ -138,6 +138,10 @@ namespace NzbDrone.Core.Indexers
|
||||
{
|
||||
torrentRelease.IndexerFlags.Add(IndexerFlag.FreeLeech);
|
||||
}
|
||||
else if (torrentRelease.DownloadVolumeFactor == 0.5)
|
||||
{
|
||||
torrentRelease.IndexerFlags.Add(IndexerFlag.HalfLeech);
|
||||
}
|
||||
|
||||
if (torrentRelease.UploadVolumeFactor == 0.0)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Indexers
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.Trace("Invalid torrent file contents: {0}", Encoding.ASCII.GetString(fileData));
|
||||
_logger.Info("Invalid torrent file contents: {0}", Encoding.ASCII.GetString(fileData));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Add": "Přidat",
|
||||
"CertificateValidation": "Ověření certifikátu",
|
||||
"DeleteBackupMessageText": "Opravdu chcete smazat zálohu „{0}“?",
|
||||
"DeleteBackupMessageText": "Opravdu chcete odstranit zálohu '{name}'?",
|
||||
"YesCancel": "Ano, zrušit",
|
||||
"About": "O aplikaci",
|
||||
"Component": "Komponenta",
|
||||
@@ -35,7 +35,7 @@
|
||||
"Warn": "Varovat",
|
||||
"Wiki": "Wiki",
|
||||
"Connections": "Připojení",
|
||||
"DeleteDownloadClientMessageText": "Opravdu chcete odstranit klienta pro stahování „{0}“?",
|
||||
"DeleteDownloadClientMessageText": "Opravdu chcete odstranit klienta pro stahování '{name}'?",
|
||||
"Details": "Detaily",
|
||||
"Disabled": "Zakázáno",
|
||||
"Docker": "Přístavní dělník",
|
||||
@@ -114,7 +114,7 @@
|
||||
"AcceptConfirmationModal": "Přijměte potvrzovací modální okno",
|
||||
"Actions": "Akce",
|
||||
"Added": "Přidáno",
|
||||
"AddIndexer": "Přidat indexátor",
|
||||
"AddIndexer": "Přidat indexer",
|
||||
"LaunchBrowserHelpText": " Otevřete webový prohlížeč a při spuštění aplikace přejděte na domovskou stránku {appName}.",
|
||||
"Logging": "Protokolování",
|
||||
"Mechanism": "Mechanismus",
|
||||
@@ -249,7 +249,7 @@
|
||||
"DeleteApplicationMessageText": "Opravdu chcete smazat oznámení „{0}“?",
|
||||
"DeleteBackup": "Odstranit zálohu",
|
||||
"DeleteDownloadClient": "Odstranit staženého klienta",
|
||||
"DeleteNotificationMessageText": "Opravdu chcete smazat oznámení „{0}“?",
|
||||
"DeleteNotificationMessageText": "Opravdu chcete smazat oznámení '{name}'?",
|
||||
"DeleteTagMessageText": "Opravdu chcete smazat značku „{0}“?",
|
||||
"Discord": "Svár",
|
||||
"DownloadClient": "Stáhnout klienta",
|
||||
@@ -333,22 +333,22 @@
|
||||
"More": "Více",
|
||||
"ApplyTagsHelpTextAdd": "Přidat: Přidá značky k již existujícímu seznamu",
|
||||
"ApplyTagsHelpTextHowToApplyApplications": "Jak použít značky na vybrané filmy",
|
||||
"DeleteSelectedDownloadClients": "Odstranit staženého klienta",
|
||||
"DeleteSelectedIndexersMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedDownloadClients": "Odstranit klienta pro stahování",
|
||||
"DeleteSelectedIndexersMessageText": "Opravdu chcete smazat {count} vybraný(ch) indexer(ů)?",
|
||||
"DeleteSelectedApplicationsMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Opravdu chcete odstranit indexer „{0}“?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Opravdu chcete smazat {count} vybraných klientů pro stahování?",
|
||||
"Year": "Rok",
|
||||
"ApplyTagsHelpTextRemove": "Odebrat: Odebrat zadané značky",
|
||||
"DownloadClientPriorityHelpText": "Upřednostněte více klientů pro stahování. Round-Robin se používá pro klienty se stejnou prioritou.",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Jak použít značky na vybrané indexátory",
|
||||
"ApplyTagsHelpTextReplace": "Nahradit: Nahradit značky zadanými značkami (zadáním žádné značky vymažete všechny značky)",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Jak použít značky na vybrané indexery",
|
||||
"ApplyTagsHelpTextReplace": "Nahradit: Nahradit značky zadanými značkami (prázdné pole vymaže všechny značky)",
|
||||
"Track": "Stopa",
|
||||
"Genre": "Žánry",
|
||||
"ConnectionLostReconnect": "{appName} se pokusí připojit automaticky, nebo můžete kliknout na tlačítko znovunačtení níže.",
|
||||
"RecentChanges": "Nedávné změny",
|
||||
"WhatsNew": "Co je nového?",
|
||||
"DeleteAppProfileMessageText": "Opravdu chcete smazat kvalitní profil {0}",
|
||||
"ConnectionLostToBackend": "{appName} ztratila spojení s backendem a pro obnovení funkčnosti bude třeba ji znovu načíst.",
|
||||
"ConnectionLostToBackend": "{appName} ztratil spojení s backendem a pro obnovení funkčnosti bude třebaho znovu načíst.",
|
||||
"minutes": "Minut",
|
||||
"ApplicationURL": "URL aplikace",
|
||||
"ApplicationUrlHelpText": "Externí adresa URL této aplikace včetně http(s)://, portu a základní adresy URL",
|
||||
@@ -361,29 +361,29 @@
|
||||
"AddCustomFilter": "Přidat vlastní filtr",
|
||||
"AddConnection": "Přidat spojení",
|
||||
"AddConnectionImplementation": "Přidat spojení - {implementationName}",
|
||||
"AddIndexerImplementation": "Přidat indexátor - {implementationName}",
|
||||
"AddIndexerImplementation": "Přidat indexer - {implementationName}",
|
||||
"Publisher": "Vydavatel",
|
||||
"Categories": "Kategorie",
|
||||
"Notification": "Oznámení",
|
||||
"AddApplicationImplementation": "Přidat spojení - {implementationName}",
|
||||
"AddIndexerProxyImplementation": "Přidat indexátor - {implementationName}",
|
||||
"Artist": "umělec",
|
||||
"EditIndexerImplementation": "Přidat indexátor - {implementationName}",
|
||||
"Artist": "Umělec",
|
||||
"EditIndexerImplementation": "Upravit indexer - {implementationName}",
|
||||
"Episode": "epizoda",
|
||||
"NotificationStatusAllClientHealthCheckMessage": "Všechny seznamy nejsou k dispozici z důvodu selhání",
|
||||
"NotificationStatusSingleClientHealthCheckMessage": "Seznamy nejsou k dispozici z důvodu selhání: {0}",
|
||||
"Application": "Aplikace",
|
||||
"AppUpdatedVersion": "{appName} byla aktualizována na verzi `{version}`, abyste získali nejnovější změny, musíte znovu načíst {appName}.",
|
||||
"AppUpdatedVersion": "{appName} byl aktualizován na verzi `{version}`, abyste získali nejnovější změny, musíte znovu načíst {appName}",
|
||||
"Encoding": "Kódování",
|
||||
"Notifications": "Oznámení",
|
||||
"Season": "Řada",
|
||||
"Theme": "Motiv",
|
||||
"Label": "Etiketa",
|
||||
"Album": "album",
|
||||
"Album": "Album",
|
||||
"Applications": "Aplikace",
|
||||
"Connect": "Oznámení",
|
||||
"EditConnectionImplementation": "Přidat spojení - {implementationName}",
|
||||
"EditDownloadClientImplementation": "Přidat klienta pro stahování - {implementationName}",
|
||||
"EditDownloadClientImplementation": "Upravit klienta pro stahování - {implementationName}",
|
||||
"AuthForm": "Formuláře (přihlašovací stránka)",
|
||||
"Clone": "Klonovat",
|
||||
"DefaultNameCopiedProfile": "{name} - Kopírovat",
|
||||
@@ -393,9 +393,17 @@
|
||||
"ResetAPIKeyMessageText": "Opravdu chcete resetovat klíč API?",
|
||||
"Database": "Databáze",
|
||||
"CountDownloadClientsSelected": "{count} vybraných klientů ke stahování",
|
||||
"CountIndexersSelected": "{count} vybraných indexátorů",
|
||||
"CountIndexersSelected": "{count} vybraných indexerů",
|
||||
"EditIndexerProxyImplementation": "Přidat indexátor - {implementationName}",
|
||||
"AuthBasic": "Základní (vyskakovací okno prohlížeče)",
|
||||
"AuthenticationRequiredWarning": "Aby se zabránilo vzdálenému přístupu bez ověření, vyžaduje nyní {appName} povolení ověření. Ověřování z místních adres můžete volitelně zakázat.",
|
||||
"RestartProwlarr": "Restartujte {appName}"
|
||||
"RestartProwlarr": "Restartujte {appName}",
|
||||
"Duration": "Trvání",
|
||||
"EditSelectedDownloadClients": "Upravit vybrané klienty pro stahování",
|
||||
"EditSelectedIndexers": "Upravit vybrané indexery",
|
||||
"AuthenticationMethod": "Metoda ověřování",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Vložte nové heslo",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Vložte nové uživatelské jméno",
|
||||
"AuthenticationMethodHelpTextWarning": "Prosím vyberte platnou metodu ověřování",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Potvrďte nové heslo"
|
||||
}
|
||||
|
||||
@@ -280,23 +280,23 @@
|
||||
"ProwlarrSupportsAnyIndexer": "{appName} unterstützt alle Indexer, welcher den Newznab/Torznab Standard implementiert (verwende 'Generic Newznab' (für Usenet) oder 'Generic Torznab' (für Torrents)) und darüber hinaus viele weitere Indexer. Wählen Sie im Folgenden Ihren Indexer aus der Liste.",
|
||||
"Proxies": "Proxies",
|
||||
"Proxy": "Proxy",
|
||||
"ProxyBypassFilterHelpText": "Verwende ',' als Trennzeichen und '*.' als Platzhalter für Subdomains",
|
||||
"ProxyBypassFilterHelpText": "Verwenden Sie ',' als Trennzeichen und '*.' als Wildcard für Subdomains",
|
||||
"ProxyCheckBadRequestMessage": "Proxy konnte nicht getestet werden. StatusCode: {0}",
|
||||
"ProxyCheckFailedToTestMessage": "Proxy konnte nicht getestet werden: {0}",
|
||||
"ProxyCheckResolveIpMessage": "Fehler beim Auflösen der IP-Adresse für den konfigurierten Proxy-Host {0}",
|
||||
"ProxyPasswordHelpText": "Nur wenn ein Benutzername und Passwort erforderlich ist, muss es eingegeben werden. Ansonsten leer lassen.",
|
||||
"ProxyType": "Proxy Typ",
|
||||
"ProxyUsernameHelpText": "Nur wenn ein Benutzername und Passwort erforderlich ist, muss es eingegeben werden. Ansonsten leer lassen.",
|
||||
"ProxyPasswordHelpText": "Sie müssen nur einen Benutzernamen und ein Passwort eingeben, wenn dies erforderlich ist. Andernfalls lassen Sie sie leer.",
|
||||
"ProxyType": "Proxy-Typ",
|
||||
"ProxyUsernameHelpText": "Sie müssen nur einen Benutzernamen und ein Passwort eingeben, wenn dies erforderlich ist. Andernfalls lassen Sie sie leer.",
|
||||
"Public": "Öffentlich",
|
||||
"Query": "Abfrage",
|
||||
"QueryOptions": "Abfrage-Optionen",
|
||||
"QueryResults": "Abfrageergebnisse",
|
||||
"Queue": "Warteschlange",
|
||||
"Queued": "In der Warteschlange",
|
||||
"Queued": "In Warteschlange",
|
||||
"RSS": "RSS",
|
||||
"RSSIsNotSupportedWithThisIndexer": "RSS wird von diesem Indexer nicht unterstützt",
|
||||
"RawSearchSupported": "Raw-Suche unterstützt",
|
||||
"ReadTheWikiForMoreInformation": "Lese das Wiki für mehr Informationen",
|
||||
"ReadTheWikiForMoreInformation": "Lesen Sie das Wiki für weitere Informationen",
|
||||
"Reddit": "Reddit",
|
||||
"Redirect": "Umleiten",
|
||||
"RedirectHelpText": "Eingehende Download-Anfragen für den Indexer umleiten, anstatt Proxying mit {appName}",
|
||||
@@ -493,7 +493,7 @@
|
||||
"Book": "Buch",
|
||||
"ConnectionLostReconnect": "Radarr wird automatisch versuchen zu verbinden oder klicke unten auf neuladen.",
|
||||
"ConnectionLostToBackend": "Radarr hat die Verbindung zum Backend verloren und muss neugeladen werden.",
|
||||
"RecentChanges": "Neuste Änderungen",
|
||||
"RecentChanges": "Kürzliche Änderungen",
|
||||
"WhatsNew": "Was gibt's Neues?",
|
||||
"minutes": "Minuten",
|
||||
"DeleteAppProfileMessageText": "Qualitätsprofil '{0}' wirklich löschen?",
|
||||
@@ -516,5 +516,21 @@
|
||||
"VipExpiration": "VIP Ablaufdatum",
|
||||
"TotalUserAgentQueries": "Gesamte Nutzeragent Anfragen",
|
||||
"ActiveApps": "Aktive Apps",
|
||||
"ActiveIndexers": "Aktive Indexer"
|
||||
"ActiveIndexers": "Aktive Indexer",
|
||||
"AppsMinimumSeeders": "Apps Mindestanzahl von Seedern",
|
||||
"ApplicationTagsHelpText": "Synchronisiere Indexer für diese Anwendung die keine passenden Tags oder mindestens 1 passendes Tag haben",
|
||||
"ApplicationTagsHelpTextWarning": "Tags sollten mit Vorsicht verwendet werden, da sie ungewollte Effekte haben können. Eine Anwendung mit einem Tag synchronisiert nur Indexer die den Gleichen Tag haben.",
|
||||
"AddApplicationImplementation": "Anwendung hinzufügen - {implementationName}",
|
||||
"AddConnectionImplementation": "Verbindung hinzufügen - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Download-Client hinzufügen - {implementationName}",
|
||||
"AddIndexerImplementation": "Indexer hinzufügen - {implementationName}",
|
||||
"AddIndexerProxyImplementation": "Indexer Proxy hinzufügen - {implementationName}",
|
||||
"AppUpdatedVersion": "{appName} wurde auf die Version `{version}` aktualisiert. Um die neusten Funktionen zu bekommen lade {appName} neu",
|
||||
"AuthenticationRequiredWarning": "Um unberechtigte Fernzugriffe zu vermeiden benötigt {appName} jetzt , dass Authentifizierung eingeschaltet ist. Du kannst Authentifizierung optional für lokale Adressen ausschalten.",
|
||||
"AuthenticationRequired": "Authentifizierung benötigt",
|
||||
"AuthenticationRequiredHelpText": "Ändern, welche anfragen Authentifizierung benötigen. Ändere nichts wenn du dir nicht des Risikos bewusst bist.",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Gib einen neuen Benutzernamen ein",
|
||||
"AuthenticationMethodHelpTextWarning": "Bitte wähle eine gültige Authentifizierungsmethode aus",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Gib ein neues Passwort ein",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Neues Passwort bestätigen"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Indexers": "Indexadores",
|
||||
"Host": "Host",
|
||||
"History": "Historia",
|
||||
"History": "Historial",
|
||||
"HideAdvanced": "Ocultar Avanzado",
|
||||
"Health": "Salud",
|
||||
"General": "General",
|
||||
@@ -53,7 +53,7 @@
|
||||
"Queue": "Cola",
|
||||
"ProxyCheckResolveIpMessage": "No se pudo resolver la dirección IP del Host Proxy configurado {0}",
|
||||
"ProxyCheckFailedToTestMessage": "Fallo al comprobar el proxy: {0}",
|
||||
"ProxyCheckBadRequestMessage": "Fallo al comprobar el proxy. StatusCode: {0}",
|
||||
"ProxyCheckBadRequestMessage": "Fallo al comprobar el proxy. Status code: {0}",
|
||||
"Proxy": "Proxy",
|
||||
"Options": "Opciones",
|
||||
"NoChange": "Sin Cambio",
|
||||
@@ -65,7 +65,7 @@
|
||||
"IndexerStatusCheckAllClientMessage": "Los indexers no están disponibles debido a errores",
|
||||
"Added": "Añadido",
|
||||
"Actions": "Acciones",
|
||||
"UISettingsSummary": "Calendario, fecha y opciones de color deteriorado",
|
||||
"UISettingsSummary": "Fecha, idioma, y opciones de color deteriorado",
|
||||
"TagsSettingsSummary": "Ver todas las etiquetas y cómo se usan. Las etiquetas no utilizadas se pueden eliminar",
|
||||
"Size": "Tamaño",
|
||||
"ReleaseStatus": "Estado del Estreno",
|
||||
@@ -74,14 +74,14 @@
|
||||
"IndexerStatusCheckSingleClientMessage": "Indexers no disponibles debido a errores: {0}",
|
||||
"Indexer": "Indexador",
|
||||
"Grabbed": "Añadido",
|
||||
"GeneralSettingsSummary": "Puerto, SSL, nombre de usuario/contraseña , proxy, analíticas y actualizaciones",
|
||||
"GeneralSettingsSummary": "Puerto, SSL, nombre de usuario/contraseña , proxy, analíticas, y actualizaciones",
|
||||
"Filename": "Nombre del archivo",
|
||||
"Failed": "Fallido",
|
||||
"EventType": "Tipo de Evento",
|
||||
"DownloadClientsSettingsSummary": "Gestores de descargas, manipulación de descargas y mapeados remotos",
|
||||
"DownloadClientsSettingsSummary": "Configuración del cliente de descargas para la integración en {appName} UI search",
|
||||
"DownloadClient": "Gestor de Descargas",
|
||||
"Details": "Detalles",
|
||||
"ConnectSettingsSummary": "Notificaciones, conexiones a servidores/reproductores y scripts personalizados",
|
||||
"ConnectSettingsSummary": "Notificaciones y scripts personalizados",
|
||||
"Warn": "Advertencia",
|
||||
"Type": "Tipo",
|
||||
"Title": "Título",
|
||||
@@ -140,10 +140,10 @@
|
||||
"DeleteBackup": "Borrar Backup",
|
||||
"DBMigration": "Migración de DB",
|
||||
"CloneProfile": "Clonar Perfil",
|
||||
"ClientPriority": "Prioridad de Cliente",
|
||||
"ClientPriority": "Prioridad del Cliente",
|
||||
"ChangeHasNotBeenSavedYet": "El cambio aún no se ha guardado",
|
||||
"CertificateValidationHelpText": "Cambiar la rigidez de la validación de la certificación HTTPS",
|
||||
"CertificateValidation": "Validación del certificado",
|
||||
"CertificateValidation": "Validacion de certificado",
|
||||
"BypassProxyForLocalAddresses": "Omitir Proxy para Direcciones Locales",
|
||||
"Branch": "Rama",
|
||||
"BindAddressHelpText": "Dirección IP4 válida, localhost o '*' para todas las interfaces",
|
||||
@@ -167,7 +167,7 @@
|
||||
"URLBase": "URL Base",
|
||||
"Uptime": "Tiempo de actividad",
|
||||
"UpdateScriptPathHelpText": "Ruta del script propio que toma el paquete de actualización y se encarga del proceso de actualización restante",
|
||||
"UpdateMechanismHelpText": "Usar el actualizador de {appName} o un script",
|
||||
"UpdateMechanismHelpText": "Usar el actualizador incorporado de {appName} o un script",
|
||||
"UpdateAutomaticallyHelpText": "Descargar e instalar actualizaciones automáticamente. Se podrán instalar desde Sistema: Actualizaciones también",
|
||||
"UnableToLoadTags": "No se pueden cargar las Etiquetas",
|
||||
"UnableToLoadNotifications": "No se pueden cargar las Notificaciones",
|
||||
@@ -236,13 +236,13 @@
|
||||
"ExistingTag": "Etiqueta existente",
|
||||
"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}",
|
||||
"DeleteTagMessageText": "Seguro que quieres eliminar la etiqueta '{0}'?",
|
||||
"DeleteNotificationMessageText": "Seguro que quieres elminiar la notificación '{0}'?",
|
||||
"DeleteBackupMessageText": "Seguro que quieres eliminar la copia de seguridad '{0}'?",
|
||||
"DeleteDownloadClientMessageText": "Seguro que quieres eliminar el gestor de descargas '{0}'?",
|
||||
"CancelPendingTask": "Seguro que quieres cancelar esta tarea pendiente?",
|
||||
"BranchUpdateMechanism": "Rama usada por el mecanismo de actualización externo",
|
||||
"BranchUpdate": "Qué rama usar para actualizar {appName}",
|
||||
"DeleteTagMessageText": "¿Está seguro de querer eliminar la etiqueta '{label}'?",
|
||||
"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 gestor de descargas '{name}'?",
|
||||
"CancelPendingTask": "Estas seguro de que deseas cancelar esta tarea pendiente?",
|
||||
"BranchUpdateMechanism": "La rama se uso por un mecanisco de actualizacion externo",
|
||||
"BranchUpdate": "Rama a usar para actualizar {appName}",
|
||||
"BeforeUpdate": "Antes de actualizar",
|
||||
"AddingTag": "Añadir etiqueta",
|
||||
"UnableToLoadUISettings": "No se han podido cargar los ajustes de UI",
|
||||
@@ -256,12 +256,12 @@
|
||||
"StartTypingOrSelectAPathBelow": "Comienza a escribir o selecciona una ruta debajo",
|
||||
"Restore": "Restaurar",
|
||||
"ProwlarrSupportsAnyIndexer": "{appName} soporta cualquier indexer que utilice el estandar Newznab, como también cualquiera de los indexers listados debajo.",
|
||||
"ProwlarrSupportsAnyDownloadClient": "Raddar soporta cualquier gestor de descargas que utilice el estandar Newznab, como también los clientes indicados debajo.",
|
||||
"ProwlarrSupportsAnyDownloadClient": "{appName} soporta cualquier gestor de descargas indicado debajo.",
|
||||
"NoUpdatesAreAvailable": "No hay actualizaciones disponibles",
|
||||
"NoTagsHaveBeenAddedYet": "No se han añadido etiquetas todavía",
|
||||
"NoLogFiles": "Sin archivos de registro",
|
||||
"NoBackupsAreAvailable": "No hay copias de seguridad disponibles",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento",
|
||||
"MaintenanceRelease": "Lanzamiento de mantenimiento: Corrección de errores y otras mejoras. Ver historial de commits de Github para mas detalle",
|
||||
"ForMoreInformationOnTheIndividualDownloadClients": "Para más información individual de los gestores de descarga, haz clic en lls botones de información.",
|
||||
"FilterPlaceHolder": "Buscar películas",
|
||||
"Exception": "Excepción",
|
||||
@@ -288,7 +288,7 @@
|
||||
"IndexerLongTermStatusCheckAllClientMessage": "Ningún indexer está disponible por errores durando más de 6 horas",
|
||||
"Reddit": "Reddit",
|
||||
"UnableToAddANewAppProfilePleaseTryAgain": "No se ha podido añadir un nuevo perfil de calidad, prueba otra vez.",
|
||||
"DeleteIndexerProxyMessageText": "Seguro que quieres eliminar la etiqueta '{0}'?",
|
||||
"DeleteIndexerProxyMessageText": "¿Seguro que quieres eliminar el proxy indexador '{name}'?",
|
||||
"Discord": "Discord",
|
||||
"Add": "Añadir",
|
||||
"Custom": "Personalizado",
|
||||
@@ -307,7 +307,7 @@
|
||||
"ApplicationStatusCheckAllClientMessage": "Las listas no están disponibles debido a errores",
|
||||
"ApplicationStatusCheckSingleClientMessage": "Listas no disponibles debido a errores: {0}",
|
||||
"AllIndexersHiddenDueToFilter": "Todos los indexadores están ocultas debido al filtro aplicado.",
|
||||
"DeleteApplicationMessageText": "Seguro que quieres elminiar la notificación '{0}'?",
|
||||
"DeleteApplicationMessageText": "Seguro que quieres eliminar la notificación '{name}'?",
|
||||
"IndexerProxyStatusCheckAllClientMessage": "Los indexers no están disponibles debido a errores",
|
||||
"IndexerProxyStatusCheckSingleClientMessage": "Indexers no disponibles debido a errores: {0}",
|
||||
"NoLinks": "Sin enlaces",
|
||||
@@ -333,7 +333,7 @@
|
||||
"Applications": "Aplicaciones",
|
||||
"AppProfileInUse": "Perfil de aplicación en uso",
|
||||
"AddDownloadClientToProwlarr": "Añadir un cliente de descargas permite a {appName} enviar descargas directamente desde la interfaz en una búsqueda manual.",
|
||||
"Category": "Categoría",
|
||||
"Category": "Categoria",
|
||||
"Application": "Aplicación",
|
||||
"BookSearch": "Búsqueda de libros",
|
||||
"BookSearchTypes": "Tipos de búsqueda de libros",
|
||||
@@ -375,14 +375,14 @@
|
||||
"ApplyTagsHelpTextAdd": "Añadir: Añadir a las etiquetas la lista existente de etiquetas",
|
||||
"DeleteSelectedApplicationsMessageText": "Seguro que quieres eliminar el indexer '{0}'?",
|
||||
"DeleteSelectedDownloadClients": "Borrar Gestor de Descargas",
|
||||
"DeleteSelectedIndexersMessageText": "Seguro que quieres eliminar el indexer '{0}'?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "¿Está seguro de querer eliminar {0} cliente(s) de descarga seleccionado(s)?",
|
||||
"DeleteSelectedIndexersMessageText": "¿Está seguro de querer eliminar {count} indexador(es) seleccionado(s)?",
|
||||
"DeleteSelectedDownloadClientsMessageText": "¿Está seguro de querer eliminar {count} cliente(s) de descarga seleccionado(s)?",
|
||||
"ApplyTagsHelpTextHowToApplyApplications": "Cómo añadir etiquetas a las películas seleccionadas",
|
||||
"SelectIndexers": "Buscar películas",
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Cómo añadir etiquetas a los indexadores seleccionados",
|
||||
"ApplyTagsHelpTextRemove": "Eliminar: Eliminar las etiquetas introducidas",
|
||||
"ApplyTagsHelpTextReplace": "Reemplazar: Reemplazar las etiquetas con las etiquetas introducidas (no introducir etiquetas para eliminar todas las etiquetas)",
|
||||
"ThemeHelpText": "Cambia el tema de la interfaz de usuario de la aplicación. El tema \"automático\" utilizará el tema de tu sistema operativo para establecer el modo claro u oscuro. Inspirado por Theme.Park",
|
||||
"ThemeHelpText": "Cambia el tema de la interfaz de usuario de la aplicación. El tema \"automático\" utilizará el tema de tu sistema operativo para establecer el modo claro u oscuro. Inspirado por {inspiredBy}.",
|
||||
"DownloadClientPriorityHelpText": "Priorizar múltiples Gestores de Descargas. Se usa Round-Robin para gestores con la misma prioridad.",
|
||||
"Season": "Temporada",
|
||||
"More": "Más",
|
||||
@@ -393,8 +393,8 @@
|
||||
"Publisher": "Editor",
|
||||
"AuthenticationRequired": "Autenticación requerida",
|
||||
"ApplyChanges": "Aplicar Cambios",
|
||||
"CountIndexersSelected": "{0} indexador(es) seleccionado(s)",
|
||||
"CountDownloadClientsSelected": "{0} cliente(s) de descarga seleccionado(s)",
|
||||
"CountIndexersSelected": "{count} indexador(es) seleccionado(s)",
|
||||
"CountDownloadClientsSelected": "{count} cliente(s) de descarga seleccionado(s)",
|
||||
"EditSelectedDownloadClients": "Editar Clientes de Descarga Seleccionados",
|
||||
"EditSelectedIndexers": "Editar Indexadores Seleccionados",
|
||||
"Implementation": "Implementación",
|
||||
@@ -405,7 +405,7 @@
|
||||
"ConnectionLostReconnect": "Radarr intentará conectarse automáticamente, o haz clic en el botón de recarga abajo.",
|
||||
"ConnectionLostToBackend": "Radarr ha perdido su conexión con el backend y tendrá que ser recargado para recuperar su funcionalidad.",
|
||||
"RecentChanges": "Cambios recientes",
|
||||
"WhatsNew": "¿Qué hay de nuevo?",
|
||||
"WhatsNew": "Que es lo nuevo?",
|
||||
"minutes": "Minutos",
|
||||
"Album": "álbum",
|
||||
"Artist": "artista",
|
||||
@@ -413,7 +413,7 @@
|
||||
"AddConnection": "Añadir Conexión",
|
||||
"NotificationStatusAllClientHealthCheckMessage": "Las listas no están disponibles debido a errores",
|
||||
"NotificationStatusSingleClientHealthCheckMessage": "Listas no disponibles debido a errores: {0}",
|
||||
"EditIndexerImplementation": "Agregar Condición - { implementationName}",
|
||||
"EditIndexerImplementation": "Editar indexador - {implementationName}",
|
||||
"AuthBasic": "Básico (ventana emergente del navegador)",
|
||||
"AuthForm": "Formularios (página de inicio de sesión)",
|
||||
"Author": "Autor",
|
||||
@@ -441,5 +441,56 @@
|
||||
"AuthenticationRequiredWarning": "Para evitar el acceso remoto sin autenticación, {appName} ahora requiere que la autenticación esté habilitada. Opcionalmente puede desactivar la autenticación desde una dirección local.",
|
||||
"EditDownloadClientImplementation": "Añadir Cliente de Descarga - {implementationName}",
|
||||
"DefaultNameCopiedProfile": "{name} - Copia",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirma la nueva contraseña"
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Confirma la nueva contraseña",
|
||||
"NoHistoryFound": "No se encontró historial",
|
||||
"DeleteApplication": "Eliminar Aplicación",
|
||||
"AreYouSureYouWantToDeleteCategory": "Esta seguro que desea eliminar la categoría mapeada?",
|
||||
"AdvancedSettingsHiddenClickToShow": "Configuraciones avanzadas escondidas, click para mostrar",
|
||||
"AdvancedSettingsShownClickToHide": "Se muestran las configuraciones avanzadas, click para esconder",
|
||||
"AppsMinimumSeeders": "Semillas mínimas para las Aplicaciones",
|
||||
"ClearHistoryMessageText": "Esta seguro que desea borrar todo el historial de {appName}?",
|
||||
"ClearHistory": "Borrar Historial",
|
||||
"AreYouSureYouWantToDeleteIndexer": "Esta seguro que desea eliminar '{name}' de {appName}?",
|
||||
"AuthQueries": "Consultas de Autorización",
|
||||
"ApplicationTagsHelpText": "Sincronizar los Indexadores a esta aplicación que no tengan etiquetas o que tengan al menos una etiqueta coincidente",
|
||||
"ApplicationTagsHelpTextWarning": "Las etiquetas deben utilizarse con cuidado, pueden tener efectos involuntarios. Una aplicación con una etiqueta solo sincronizara con Indexadores que tengan la misma etiqueta.",
|
||||
"AppsMinimumSeedersHelpText": "Cantidad mínima de semillas requerida por las Aplicaciones para que el Indexador capture, vacío aplica la configuración por defecto del perfil",
|
||||
"AverageResponseTimesMs": "Tiempo promedio de respuesta del Indexador (ms)",
|
||||
"CountIndexersAvailable": "{count} indexadores disponibles",
|
||||
"DeleteAppProfile": "Eliminar Perfil de Aplicación",
|
||||
"AddSyncProfile": "Agregar Perfil de Sincronización",
|
||||
"AppSettingsSummary": "Aplicaciones y configuraciones para determinar como {appName} interactúa con sus programas de PVR",
|
||||
"AddCategory": "Agregar Categoría",
|
||||
"AppProfileSelectHelpText": "Los perfiles de la aplicación se usan para controlar la configuración por aplicación de RSS, Búsqueda Automática y Búsqueda Interactiva",
|
||||
"ActiveApps": "Aplicaciones Activas",
|
||||
"ActiveIndexers": "Indexadores Activos",
|
||||
"AudioSearch": "Búsqueda de Música",
|
||||
"Auth": "Autenticación",
|
||||
"BasicSearch": "Búsqueda Básica",
|
||||
"CountApplicationsSelected": "{count} aplicaciones seleccionadas",
|
||||
"IndexerHealthCheckNoIndexers": "Ningún indexador habilitado, {appName} no devolverá resultados de búsqueda",
|
||||
"IndexerAuth": "Autentificación de indexador",
|
||||
"DeleteSelectedApplications": "Eliminar aplicaciones seleccionadas",
|
||||
"DeleteSelectedIndexer": "Eliminar indexador seleccionado",
|
||||
"IndexerCategories": "Categorías de indexador",
|
||||
"IndexerDownloadClientHelpText": "Especifique qué cliente de descarga se utiliza para capturas hechas desde {appName} a partir de este indexador",
|
||||
"FullSync": "Sincronización total",
|
||||
"GoToApplication": "Ir a la aplicación",
|
||||
"FoundCountReleases": "{itemCount} releases hallados",
|
||||
"HistoryDetails": "Detalles de historial",
|
||||
"DeleteClientCategory": "Eliminar categoría de cliente de descarga",
|
||||
"DeleteSelectedIndexers": "Eliminar indexadores seleccionados",
|
||||
"DevelopmentSettings": "Ajustes de desarrollo",
|
||||
"EnabledRedirected": "Habilitado, redireccionado",
|
||||
"IndexerDetails": "Detalles de indexador",
|
||||
"IndexerDisabled": "Indexador deshabilitado",
|
||||
"IndexerFailureRate": "Tasa de fallo del indexador",
|
||||
"IndexerAlreadySetup": "Hay al menos una instancia de indexador configurada",
|
||||
"DisabledUntil": "Deshabilitado hasta",
|
||||
"DownloadClientCategory": "Categoría de cliente de descarga",
|
||||
"HistoryCleanup": "Limpieza de historial",
|
||||
"Id": "Id",
|
||||
"EditCategory": "Editar categoría",
|
||||
"EditSyncProfile": "Editar perfil de sincronización",
|
||||
"EnableIndexer": "Habilitar indexador"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"Indexers": "Indexeurs",
|
||||
"Host": "Hôte",
|
||||
"History": "Historique",
|
||||
"HideAdvanced": "Masquer param. av.",
|
||||
"HideAdvanced": "Masquer les Options Avancées",
|
||||
"Health": "Santé",
|
||||
"General": "Général",
|
||||
"Folder": "Dossier",
|
||||
@@ -12,7 +12,7 @@
|
||||
"Events": "Événements",
|
||||
"Edit": "Modifier",
|
||||
"DownloadClientStatusCheckAllClientMessage": "Aucun client de téléchargement n'est disponible en raison d'échecs",
|
||||
"DownloadClients": "Clients de télécharg.",
|
||||
"DownloadClients": "Clients de téléchargement",
|
||||
"Dates": "Dates",
|
||||
"Date": "Date",
|
||||
"Delete": "Supprimer",
|
||||
@@ -207,7 +207,7 @@
|
||||
"ProxyBypassFilterHelpText": "Utilisez ',' comme séparateur et '*.' comme caractère générique pour les sous-domaines",
|
||||
"Uptime": "Disponibilité",
|
||||
"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",
|
||||
"UnableToLoadUISettings": "Impossible de charger les paramètres de l'interface utilisateur",
|
||||
"UnableToLoadTags": "Impossible de charger les étiquettes",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"ChangeHasNotBeenSavedYet": "Perubahan belum disimpan",
|
||||
"EnableInteractiveSearch": "Aktifkan Penelusuran Interaktif",
|
||||
"Ended": "Berakhir",
|
||||
"AuthenticationMethodHelpText": "Perlukan Nama Pengguna dan Sandi untuk mengakses Radarr",
|
||||
"AuthenticationMethodHelpText": "Perlukan Nama Pengguna dan Sandi untuk mengakses {appName}",
|
||||
"Host": "Host",
|
||||
"Enable": "Aktif",
|
||||
"EnableRss": "Aktifkan RSS",
|
||||
@@ -34,7 +34,7 @@
|
||||
"Categories": "Kategori",
|
||||
"Close": "Tutup",
|
||||
"ConnectionLost": "Koneksi Terputus",
|
||||
"Connections": "Koleksi",
|
||||
"Connections": "Koneksi",
|
||||
"Custom": "Khusus",
|
||||
"Dates": "Tanggal",
|
||||
"Delete": "Hapus",
|
||||
@@ -46,7 +46,7 @@
|
||||
"Hostname": "Hostname",
|
||||
"Info": "Informasi",
|
||||
"Language": "Bahasa",
|
||||
"LogFiles": "Berkas Log",
|
||||
"LogFiles": "File Log",
|
||||
"NoChange": "Tidak Ada Perubahan",
|
||||
"NoChanges": "Tidak Ada Perubahan",
|
||||
"Queued": "Antrean",
|
||||
@@ -58,7 +58,25 @@
|
||||
"Actions": "Tindakan",
|
||||
"AllIndexersHiddenDueToFilter": "Semua film disembunyikan karena penyaringan yang diterapkan.",
|
||||
"AnalyticsEnabledHelpText": "Kirimkan informasi penggunaan secara anonim ke server Radarr. Informasi tersebut mengandung browser kamu, halaman WebUI Radarr yang kamu gunakan, pelaporan masalah serta OS dan versi runtime. Kami akan memanfaatkan informasi ini untuk memprioritaskan fitur dan perbaikan bug.",
|
||||
"ConnectionLostReconnect": "Radarr akan mencoba untuk menghubungi secara otomatis, atau klik muat ulang di bawah.",
|
||||
"ConnectionLostReconnect": "{appName} akan mencoba untuk menghubungkan secara otomatis, atau silakan klik muat ulang di bawah.",
|
||||
"AuthBasic": "Dasar (Popup Browser)",
|
||||
"AuthForm": "Formulir (Halaman Login)"
|
||||
"AuthForm": "Formulir (Halaman Masuk)",
|
||||
"Category": "Kategori",
|
||||
"ApplyChanges": "Terapkan Perubahan",
|
||||
"Today": "Hari Ini",
|
||||
"Yesterday": "Kemarin",
|
||||
"Search": "Cari",
|
||||
"ConnectSettings": "Pengaturan Koneksi",
|
||||
"Refresh": "Muat Ulang",
|
||||
"ConnectionLostToBackend": "Koneksi {appName} telah terputus dari backend dan perlu dimuat ulang untuk dipulihkan.",
|
||||
"Edit": "Edit",
|
||||
"Files": "File",
|
||||
"History": "Riwayat",
|
||||
"AuthenticationMethod": "Metode Autentikasi",
|
||||
"AuthenticationMethodHelpTextWarning": "Silakan pilih metode autentikasi yang sah",
|
||||
"AuthenticationRequired": "Autentikasi Diperlukan",
|
||||
"AuthenticationRequiredPasswordHelpTextWarning": "Masukkan sandi baru",
|
||||
"AuthenticationRequiredUsernameHelpTextWarning": "Masukkan nama pengguna baru",
|
||||
"AuthenticationRequiredWarning": "Untuk mencegah akses jarak jauh tanpa autentikasi, {appName} kini mewajibkan pengaktifkan autentikasi. Kamu dapat menonaktifkan autentikasi dari jaringan lokal.",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "Konfirmasi sandi baru"
|
||||
}
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
{}
|
||||
{
|
||||
"About": "Par",
|
||||
"AcceptConfirmationModal": "Apstiprināt Apstiprināšanas Modālu",
|
||||
"Actions": "Darbības",
|
||||
"Add": "Pievienot",
|
||||
"AddDownloadClient": "Pievienot Lejupielādes Klientu",
|
||||
"AddConnection": "Pievienot Savienojumu",
|
||||
"AddConnectionImplementation": "Pievienot Savienojumu - {implementationName}"
|
||||
}
|
||||
|
||||
@@ -90,9 +90,9 @@
|
||||
"DeleteApplication": "Applicatie verwijderen",
|
||||
"DeleteApplicationMessageText": "Weet u zeker dat u de applicatie '{0}' wilt verwijderen?",
|
||||
"DeleteBackup": "Verwijder Backup",
|
||||
"DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{0}' wilt verwijderen?",
|
||||
"DeleteBackupMessageText": "Bent u zeker dat u de veiligheidskopie '{name}' wilt verwijderen?",
|
||||
"DeleteDownloadClient": "Verwijder Downloader",
|
||||
"DeleteDownloadClientMessageText": "Bent u zeker dat u de downloader '{0}' wilt verwijderen?",
|
||||
"DeleteDownloadClientMessageText": "Bent u zeker dat u de downloader '{name}' wilt verwijderen?",
|
||||
"DeleteIndexerProxy": "Indexeerproxy verwijderen",
|
||||
"DeleteIndexerProxyMessageText": "Weet u zeker dat u de proxy '{0}' wilt verwijderen?",
|
||||
"DeleteNotification": "Verwijder Notificatie",
|
||||
@@ -425,7 +425,7 @@
|
||||
"ApplyTagsHelpTextHowToApplyIndexers": "Hoe tags toepassen op de geselecteerde indexeerders",
|
||||
"ApplyTagsHelpTextRemove": "Verwijderen: Verwijder de ingevoerde tags",
|
||||
"ApplyTagsHelpTextReplace": "Vervangen: Vervang de tags met de ingevoerde tags (vul geen tags in om alle tags te wissen)",
|
||||
"CountIndexersSelected": "{0} Indexer(s) Geselecteerd",
|
||||
"CountIndexersSelected": "{count} Indexer(s) Geselecteerd",
|
||||
"DeleteSelectedApplicationsMessageText": "Bent u zeker dat u de indexeerder '{0}' wilt verwijderen?",
|
||||
"DeleteSelectedDownloadClients": "Verwijder Downloader",
|
||||
"DeleteSelectedDownloadClientsMessageText": "Bent u zeker dat u de indexeerder '{0}' wilt verwijderen?",
|
||||
@@ -458,7 +458,7 @@
|
||||
"None": "Geen",
|
||||
"ResetAPIKeyMessageText": "Bent u zeker dat u uw API-sleutel wilt resetten?",
|
||||
"AddConnectionImplementation": "Voeg connectie toe - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Voeg Downloadclient toe - {implementationName}",
|
||||
"AddDownloadClientImplementation": "Voeg Downloadclient Toe - {implementationName}",
|
||||
"AddIndexerImplementation": "Indexeerder toevoegen - {implementationName}",
|
||||
"AdvancedSettingsHiddenClickToShow": "Geavanceerde instellingen zijn verborgen, klik om te tonen",
|
||||
"AdvancedSettingsShownClickToHide": "Geavanceerde instellingen worden getoond, klik om te verbergen",
|
||||
@@ -473,5 +473,8 @@
|
||||
"AddApplicationImplementation": "Voeg connectie toe - {implementationName}",
|
||||
"AddIndexerProxyImplementation": "Indexeerder toevoegen - {implementationName}",
|
||||
"EditApplicationImplementation": "Voeg connectie toe - {implementationName}",
|
||||
"EditIndexerProxyImplementation": "Indexeerder toevoegen - {implementationName}"
|
||||
"EditIndexerProxyImplementation": "Indexeerder toevoegen - {implementationName}",
|
||||
"AuthenticationMethod": "Authenticatiemethode",
|
||||
"AuthenticationRequired": "Verificatie vereist",
|
||||
"AuthenticationMethodHelpTextWarning": "Selecteer een geldige verificatie methode"
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@
|
||||
"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}'.",
|
||||
"UpdateCheckStartupTranslocationMessage": "Não é possível instalar a atualização porque a pasta de inicialização '{0}' está em uma pasta de translocação de aplicativo.",
|
||||
"UpdateCheckUINotWritableMessage": "Não é possível instalar a atualização porque a pasta de IU '{0}' não pode ser gravada pelo usuário '{1}'.",
|
||||
"UpdateMechanismHelpText": "Usar o atualizador integrado do {appName} ou um script",
|
||||
"UpdateMechanismHelpText": "Use o atualizador integrado do {appName} ou um script",
|
||||
"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",
|
||||
"Uptime": "Tempo de atividade",
|
||||
|
||||
@@ -360,12 +360,5 @@
|
||||
"Categories": "Kategoriler",
|
||||
"Application": "Uygulamalar",
|
||||
"Episode": "bölüm",
|
||||
"AddApplicationImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"AddConnection": "Bağlantı Ekle",
|
||||
"AddConnectionImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"AddIndexerImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"AddIndexerProxyImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"EditConnectionImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"EditApplicationImplementation": "Koşul Ekle - {uygulama Adı}",
|
||||
"EditIndexerImplementation": "Koşul Ekle - {uygulama Adı}"
|
||||
"AddConnection": "Bağlantı Ekle"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"AllIndexersHiddenDueToFilter": "由于应用了筛选器,所有索引器都被隐藏。",
|
||||
"Analytics": "分析",
|
||||
"AnalyticsEnabledHelpText": "将匿名使用情况和错误信息发送到{appName}的服务器。这包括有关您的浏览器的信息、您使用的{appName} WebUI页面、错误报告以及操作系统和运行时版本。我们将使用此信息来确定功能和错误修复的优先级。",
|
||||
"ApiKey": "API Key",
|
||||
"ApiKey": "接口密钥 (API Key)",
|
||||
"ApiKeyValidationHealthCheckMessage": "请将API密钥更新为至少{0}个字符长。您可以通过设置或配置文件执行此操作",
|
||||
"AppDataDirectory": "AppData目录",
|
||||
"AppDataLocationHealthCheckMessage": "正在更新期间的 AppData 不会被更新删除",
|
||||
@@ -46,7 +46,7 @@
|
||||
"Authentication": "认证",
|
||||
"AuthenticationMethodHelpText": "需要用户名和密码以访问 {appName}",
|
||||
"AuthenticationRequired": "需要身份验证",
|
||||
"AuthenticationRequiredHelpText": "更改身份验证的请求。除非您了解风险,否则请勿更改。",
|
||||
"AuthenticationRequiredHelpText": "修改哪些请求需要认证。除非你了解其中的风险,否则不要更改。",
|
||||
"AuthenticationRequiredWarning": "为了防止未经身份验证的远程访问,{appName} 现在需要启用身份验证。您可以禁用本地地址的身份验证。",
|
||||
"Author": "作者",
|
||||
"Automatic": "自动化",
|
||||
@@ -139,7 +139,7 @@
|
||||
"EnableInteractiveSearchHelpText": "当手动搜索启用时使用",
|
||||
"EnableRss": "启用RSS",
|
||||
"EnableRssHelpText": "为搜刮器启用 RSS订阅",
|
||||
"EnableSSL": "启用SSL",
|
||||
"EnableSSL": "启用 SSL",
|
||||
"EnableSslHelpText": " 重启生效",
|
||||
"Enabled": "已启用",
|
||||
"EnabledRedirected": "启用, 修改",
|
||||
@@ -469,7 +469,7 @@
|
||||
"UpdateCheckStartupNotWritableMessage": "无法安装更新,因为用户“{1}”对于启动文件夹“{0}”没有写入权限。",
|
||||
"UpdateCheckStartupTranslocationMessage": "无法安装更新,因为启动文件夹“{0}”在一个应用程序迁移文件夹。Cannot install update because startup folder '{0}' is in an App Translocation folder.",
|
||||
"UpdateCheckUINotWritableMessage": "无法安装升级,因为用户“{1}”不可写入界面文件夹“{0}”。",
|
||||
"UpdateMechanismHelpText": "使用 {appName} 内置的更新器或者脚本",
|
||||
"UpdateMechanismHelpText": "使用 {appName} 内置的更新程序或脚本",
|
||||
"UpdateScriptPathHelpText": "自定义脚本的路径,该脚本处理获取的更新包并处理更新过程的其余部分",
|
||||
"Updates": "更新",
|
||||
"Uptime": "运行时间",
|
||||
@@ -597,5 +597,8 @@
|
||||
"ActiveIndexers": "活动索引器",
|
||||
"ActiveApps": "活动应用程序",
|
||||
"AppsMinimumSeeders": "应用程序最少种子数",
|
||||
"PackSeedTime": "做种时间"
|
||||
"PackSeedTime": "做种时间",
|
||||
"PasswordConfirmation": "确认密码",
|
||||
"AuthenticationRequiredPasswordConfirmationHelpTextWarning": "确认新密码",
|
||||
"InvalidUILanguage": "语言"
|
||||
}
|
||||
|
||||
@@ -93,14 +93,6 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
failures.Add(new NzbDroneValidationFailure("Path", "File does not exist"));
|
||||
}
|
||||
|
||||
foreach (var systemFolder in SystemFolders.GetSystemFolders())
|
||||
{
|
||||
if (systemFolder.IsParentPath(Settings.Path))
|
||||
{
|
||||
failures.Add(new NzbDroneValidationFailure("Path", $"Must not be a descendant of '{systemFolder}'"));
|
||||
}
|
||||
}
|
||||
|
||||
if (failures.Empty())
|
||||
{
|
||||
try
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
||||
public CustomScriptSettingsValidator()
|
||||
{
|
||||
RuleFor(c => c.Path).IsValidPath();
|
||||
RuleFor(c => c.Path).SetValidator(new SystemFolderValidator()).WithMessage("Must not be a descendant of '{systemFolder}'");
|
||||
RuleFor(c => c.Arguments).Empty().WithMessage("Arguments are no longer supported for custom scripts");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ namespace NzbDrone.Core.Notifications.Discord
|
||||
discordField.Name = "Host";
|
||||
discordField.Value = message.Host ?? string.Empty;
|
||||
break;
|
||||
case DiscordGrabFieldType.Size:
|
||||
discordField.Name = "Size";
|
||||
discordField.Value = BytesToString(message.Release.Size.GetValueOrDefault(0));
|
||||
discordField.Inline = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (discordField.Name.IsNotNullOrWhiteSpace() && discordField.Value.IsNotNullOrWhiteSpace())
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
||||
DownloadClient,
|
||||
GrabTrigger,
|
||||
Source,
|
||||
Host
|
||||
Host,
|
||||
Size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,19 @@ namespace NzbDrone.Core.Notifications.Discord
|
||||
public DiscordSettings()
|
||||
{
|
||||
//Set Default Fields
|
||||
GrabFields = new List<int> { 0, 1, 2, 3, 5, 6, 7, 8, 9 };
|
||||
GrabFields = new List<int>
|
||||
{
|
||||
(int)DiscordGrabFieldType.Release,
|
||||
(int)DiscordGrabFieldType.Indexer,
|
||||
(int)DiscordGrabFieldType.DownloadClient,
|
||||
(int)DiscordGrabFieldType.GrabTrigger,
|
||||
(int)DiscordGrabFieldType.Source,
|
||||
(int)DiscordGrabFieldType.Host,
|
||||
(int)DiscordGrabFieldType.Size
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly DiscordSettingsValidator Validator = new DiscordSettingsValidator();
|
||||
private static readonly DiscordSettingsValidator Validator = new ();
|
||||
|
||||
[FieldDefinition(0, Label = "Webhook URL", HelpText = "Discord channel webhook url")]
|
||||
public string WebHookUrl { get; set; }
|
||||
@@ -36,7 +45,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
||||
[FieldDefinition(3, Label = "Host", Advanced = true, HelpText = "Override the Host that shows for this notification, Blank is machine name", Type = FieldType.Textbox)]
|
||||
public string Author { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "On Grab Fields", Advanced = true, SelectOptions = typeof(DiscordGrabFieldType), HelpText = "Change the fields that are passed in for this 'on grab' notification", Type = FieldType.TagSelect)]
|
||||
[FieldDefinition(4, Label = "On Grab Fields", Advanced = true, SelectOptions = typeof(DiscordGrabFieldType), HelpText = "Change the fields that are passed in for this 'on grab' notification", Type = FieldType.Select)]
|
||||
public IEnumerable<int> GrabFields { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
|
||||
<PackageReference Include="System.Text.Json" Version="6.0.9" />
|
||||
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
||||
<PackageReference Include="YamlDotNet" Version="13.7.1" />
|
||||
<PackageReference Include="YamlDotNet" Version="13.1.1" />
|
||||
<PackageReference Include="AngleSharp" Version="1.0.6" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -23,8 +23,10 @@ namespace Prowlarr.Api.V1.Search
|
||||
public string ReleaseHash { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string SortTitle { get; set; }
|
||||
public bool Approved { get; set; }
|
||||
public int ImdbId { get; set; }
|
||||
public int TmdbId { get; set; }
|
||||
public int TvdbId { get; set; }
|
||||
public int TvMazeId { get; set; }
|
||||
public DateTime PublishDate { get; set; }
|
||||
public string CommentUrl { get; set; }
|
||||
public string DownloadUrl { get; set; }
|
||||
@@ -80,6 +82,9 @@ namespace Prowlarr.Api.V1.Search
|
||||
Title = releaseInfo.Title,
|
||||
SortTitle = releaseInfo.Title.NormalizeTitle(),
|
||||
ImdbId = releaseInfo.ImdbId,
|
||||
TmdbId = releaseInfo.TmdbId,
|
||||
TvdbId = releaseInfo.TvdbId,
|
||||
TvMazeId = releaseInfo.TvMazeId,
|
||||
PublishDate = releaseInfo.PublishDate,
|
||||
CommentUrl = releaseInfo.CommentUrl,
|
||||
DownloadUrl = releaseInfo.DownloadUrl,
|
||||
|
||||
@@ -5751,13 +5751,22 @@
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"approved": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"imdbId": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"tmdbId": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"tvdbId": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"tvMazeId": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"publishDate": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
|
||||
Reference in New Issue
Block a user