Compare commits

..

2 Commits

Author SHA1 Message Date
Bogdan
5d1f79f3a3 Bump FluentMigrator to official 6.2.0
(cherry picked from commit de722539d098ba67a605cc369e55209667760692)
2025-10-30 09:42:29 -05:00
Bogdan
0ef9f4c869 Fix newznab redirect database migration
(cherry picked from commit f67bc52f85fa0677f4cda5b7b7dcb30dfe31468a)
2025-10-30 09:42:03 -05:00
12 changed files with 170 additions and 73 deletions

View File

@@ -9,7 +9,7 @@ variables:
testsFolder: './_tests' testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '2.3.2' majorVersion: '2.3.0'
minorVersion: $[counter('minorVersion', 1)] minorVersion: $[counter('minorVersion', 1)]
prowlarrVersion: '$(majorVersion).$(minorVersion)' prowlarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)' buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
@@ -18,9 +18,9 @@ variables:
dotnetVersion: '8.0.405' dotnetVersion: '8.0.405'
nodeVersion: '20.X' nodeVersion: '20.X'
innoVersion: '6.2.2' innoVersion: '6.2.2'
windowsImage: 'windows-2025' windowsImage: 'windows-2022'
linuxImage: 'ubuntu-24.04' linuxImage: 'ubuntu-22.04'
macImage: 'macOS-15' macImage: 'macOS-13'
trigger: trigger:
branches: branches:

View File

@@ -5,6 +5,5 @@
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-bsd-crossbuild" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/dotnet-bsd-crossbuild/nuget/v3/index.json" /> <add key="dotnet-bsd-crossbuild" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/dotnet-bsd-crossbuild/nuget/v3/index.json" />
<add key="Mono.Posix.NETStandard" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/Mono.Posix.NETStandard/nuget/v3/index.json" /> <add key="Mono.Posix.NETStandard" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/Mono.Posix.NETStandard/nuget/v3/index.json" />
<add key="FluentMigrator" value="https://pkgs.dev.azure.com/Servarr/Servarr/_packaging/FluentMigrator/nuget/v3/index.json" />
</packageSources> </packageSources>
</configuration> </configuration>

View File

@@ -7,7 +7,7 @@ using NzbDrone.Common.Instrumentation;
namespace NzbDrone.Core.Datastore.Migration namespace NzbDrone.Core.Datastore.Migration
{ {
[Maintenance(MigrationStage.BeforeAll, TransactionBehavior.None)] [Maintenance(MigrationStage.BeforeAll, TransactionBehavior.None)]
public class DatabaseEngineVersionCheck : FluentMigrator.Migration public class DatabaseEngineVersionCheck : ForwardOnlyMigration
{ {
protected readonly Logger _logger; protected readonly Logger _logger;
@@ -22,11 +22,6 @@ namespace NzbDrone.Core.Datastore.Migration
IfDatabase("postgres").Execute.WithConnection(LogPostgresVersion); IfDatabase("postgres").Execute.WithConnection(LogPostgresVersion);
} }
public override void Down()
{
// No-op
}
private void LogSqliteVersion(IDbConnection conn, IDbTransaction tran) private void LogSqliteVersion(IDbConnection conn, IDbTransaction tran)
{ {
using (var versionCmd = conn.CreateCommand()) using (var versionCmd = conn.CreateCommand())

View File

@@ -1,5 +1,3 @@
using System.Data;
using Dapper;
using FluentMigrator; using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
@@ -10,13 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration
{ {
protected override void MainDbUpgrade() protected override void MainDbUpgrade()
{ {
Execute.WithConnection(UpdateNewznabRedirectSetting); Update.Table("Indexers").Set(new { Redirect = true }).Where(new { Implementation = "Newznab", Redirect = false });
}
private void UpdateNewznabRedirectSetting(IDbConnection conn, IDbTransaction tran)
{
var updateSql = "UPDATE \"Indexers\" SET \"Redirect\" = @Redirect WHERE \"Implementation\" = 'Newznab' AND \"Redirect\" = false";
conn.Execute(updateSql, new { Redirect = true }, transaction: tran);
} }
} }
} }

View File

@@ -6,7 +6,6 @@ using FluentMigrator.Runner.Generators;
using FluentMigrator.Runner.Initialization; using FluentMigrator.Runner.Initialization;
using FluentMigrator.Runner.Processors; using FluentMigrator.Runner.Processors;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog; using NLog;
using NLog.Extensions.Logging; using NLog.Extensions.Logging;
@@ -20,13 +19,10 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
public class MigrationController : IMigrationController public class MigrationController : IMigrationController
{ {
private readonly Logger _logger; private readonly Logger _logger;
private readonly ILoggerProvider _migrationLoggerProvider;
public MigrationController(Logger logger, public MigrationController(Logger logger)
ILoggerProvider migrationLoggerProvider)
{ {
_logger = logger; _logger = logger;
_migrationLoggerProvider = migrationLoggerProvider;
} }
public void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType) public void Migrate(string connectionString, MigrationContext migrationContext, DatabaseType databaseType)
@@ -35,16 +31,13 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
_logger.Info("*** Migrating {0} ***", connectionString); _logger.Info("*** Migrating {0} ***", connectionString);
ServiceProvider serviceProvider;
var db = databaseType == DatabaseType.SQLite ? "sqlite" : "postgres"; var db = databaseType == DatabaseType.SQLite ? "sqlite" : "postgres";
serviceProvider = new ServiceCollection() var serviceProvider = new ServiceCollection()
.AddLogging(b => b.AddNLog()) .AddLogging(b => b.AddNLog())
.AddFluentMigratorCore() .AddFluentMigratorCore()
.Configure<RunnerOptions>(cfg => cfg.IncludeUntaggedMaintenances = true) .Configure<RunnerOptions>(cfg => cfg.IncludeUntaggedMaintenances = true)
.ConfigureRunner( .ConfigureRunner(builder => builder
builder => builder
.AddPostgres() .AddPostgres()
.AddNzbDroneSQLite() .AddNzbDroneSQLite()
.WithGlobalConnectionString(connectionString) .WithGlobalConnectionString(connectionString)

View File

@@ -1,11 +1,17 @@
using FluentMigrator; using System.Data;
using FluentMigrator;
using FluentMigrator.Builders.Create; using FluentMigrator.Builders.Create;
using FluentMigrator.Builders.Create.Table; using FluentMigrator.Builders.Create.Table;
using FluentMigrator.Runner; using FluentMigrator.Runner;
using FluentMigrator.Runner.BatchParser; using FluentMigrator.Runner.BatchParser;
using FluentMigrator.Runner.Generators;
using FluentMigrator.Runner.Generators.SQLite; using FluentMigrator.Runner.Generators.SQLite;
using FluentMigrator.Runner.Initialization;
using FluentMigrator.Runner.Processors;
using FluentMigrator.Runner.Processors.SQLite; using FluentMigrator.Runner.Processors.SQLite;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace NzbDrone.Core.Datastore.Migration.Framework namespace NzbDrone.Core.Datastore.Migration.Framework
{ {
@@ -16,23 +22,40 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
return expressionRoot.Table(name).WithColumn("Id").AsInt32().PrimaryKey().Identity(); return expressionRoot.Table(name).WithColumn("Id").AsInt32().PrimaryKey().Identity();
} }
public static void AddParameter(this System.Data.IDbCommand command, object value) public static void AddParameter(this IDbCommand command, object value)
{ {
var parameter = command.CreateParameter(); var parameter = command.CreateParameter();
parameter.Value = value; parameter.Value = value;
command.Parameters.Add(parameter); command.Parameters.Add(parameter);
} }
public static IMigrationRunnerBuilder AddNzbDroneSQLite(this IMigrationRunnerBuilder builder) public static IMigrationRunnerBuilder AddNzbDroneSQLite(this IMigrationRunnerBuilder builder, bool binaryGuid = false, bool useStrictTables = false)
{ {
builder.Services builder.Services
.AddTransient<SQLiteBatchParser>() .AddTransient<SQLiteBatchParser>()
.AddScoped<SQLiteDbFactory>() .AddScoped<SQLiteDbFactory>()
.AddScoped<NzbDroneSQLiteProcessor>() .AddScoped<NzbDroneSQLiteProcessor>(sp =>
{
var factory = sp.GetService<SQLiteDbFactory>();
var logger = sp.GetService<ILogger<NzbDroneSQLiteProcessor>>();
var options = sp.GetService<IOptionsSnapshot<ProcessorOptions>>();
var connectionStringAccessor = sp.GetService<IConnectionStringAccessor>();
var sqliteQuoter = new SQLiteQuoter(false);
return new NzbDroneSQLiteProcessor(factory, sp.GetService<SQLiteGenerator>(), logger, options, connectionStringAccessor, sp, sqliteQuoter);
})
.AddScoped<ISQLiteTypeMap>(_ => new NzbDroneSQLiteTypeMap(useStrictTables))
.AddScoped<IMigrationProcessor>(sp => sp.GetRequiredService<NzbDroneSQLiteProcessor>()) .AddScoped<IMigrationProcessor>(sp => sp.GetRequiredService<NzbDroneSQLiteProcessor>())
.AddScoped<SQLiteQuoter>() .AddScoped(
.AddScoped<SQLiteGenerator>() sp =>
{
var typeMap = sp.GetRequiredService<ISQLiteTypeMap>();
return new SQLiteGenerator(
new SQLiteQuoter(binaryGuid),
typeMap,
new OptionsWrapper<GeneratorOptions>(new GeneratorOptions()));
})
.AddScoped<IMigrationGenerator>(sp => sp.GetRequiredService<SQLiteGenerator>()); .AddScoped<IMigrationGenerator>(sp => sp.GetRequiredService<SQLiteGenerator>());
return builder; return builder;
} }
} }

View File

@@ -15,6 +15,8 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
{ {
public class NzbDroneSQLiteProcessor : SQLiteProcessor public class NzbDroneSQLiteProcessor : SQLiteProcessor
{ {
private readonly SQLiteQuoter _quoter;
public NzbDroneSQLiteProcessor(SQLiteDbFactory factory, public NzbDroneSQLiteProcessor(SQLiteDbFactory factory,
SQLiteGenerator generator, SQLiteGenerator generator,
ILogger<NzbDroneSQLiteProcessor> logger, ILogger<NzbDroneSQLiteProcessor> logger,
@@ -24,6 +26,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
SQLiteQuoter quoter) SQLiteQuoter quoter)
: base(factory, generator, logger, options, connectionStringAccessor, serviceProvider, quoter) : base(factory, generator, logger, options, connectionStringAccessor, serviceProvider, quoter)
{ {
_quoter = quoter;
} }
public override void Process(AlterColumnExpression expression) public override void Process(AlterColumnExpression expression)
@@ -35,7 +38,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
if (columnIndex == -1) if (columnIndex == -1)
{ {
throw new ApplicationException(string.Format("Column {0} does not exist on table {1}.", expression.Column.Name, expression.TableName)); throw new ApplicationException($"Column {expression.Column.Name} does not exist on table {expression.TableName}.");
} }
columnDefinitions[columnIndex] = expression.Column; columnDefinitions[columnIndex] = expression.Column;
@@ -45,6 +48,28 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
ProcessAlterTable(tableDefinition); ProcessAlterTable(tableDefinition);
} }
public override void Process(AlterDefaultConstraintExpression expression)
{
var tableDefinition = GetTableSchema(expression.TableName);
var columnDefinitions = tableDefinition.Columns.ToList();
var columnIndex = columnDefinitions.FindIndex(c => c.Name == expression.ColumnName);
if (columnIndex == -1)
{
throw new ApplicationException($"Column {expression.ColumnName} does not exist on table {expression.TableName}.");
}
var changedColumn = columnDefinitions[columnIndex];
changedColumn.DefaultValue = expression.DefaultValue;
columnDefinitions[columnIndex] = changedColumn;
tableDefinition.Columns = columnDefinitions;
ProcessAlterTable(tableDefinition);
}
public override void Process(DeleteColumnExpression expression) public override void Process(DeleteColumnExpression expression)
{ {
var tableDefinition = GetTableSchema(expression.TableName); var tableDefinition = GetTableSchema(expression.TableName);
@@ -62,7 +87,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
if (columnsToRemove.Any()) if (columnsToRemove.Any())
{ {
throw new ApplicationException(string.Format("Column {0} does not exist on table {1}.", columnsToRemove.First(), expression.TableName)); throw new ApplicationException($"Column {columnsToRemove.First()} does not exist on table {expression.TableName}.");
} }
ProcessAlterTable(tableDefinition); ProcessAlterTable(tableDefinition);
@@ -78,12 +103,12 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
if (columnIndex == -1) if (columnIndex == -1)
{ {
throw new ApplicationException(string.Format("Column {0} does not exist on table {1}.", expression.OldName, expression.TableName)); throw new ApplicationException($"Column {expression.OldName} does not exist on table {expression.TableName}.");
} }
if (columnDefinitions.Any(c => c.Name == expression.NewName)) if (columnDefinitions.Any(c => c.Name == expression.NewName))
{ {
throw new ApplicationException(string.Format("Column {0} already exists on table {1}.", expression.NewName, expression.TableName)); throw new ApplicationException($"Column {expression.NewName} already exists on table {expression.TableName}.");
} }
oldColumnDefinitions[columnIndex] = (ColumnDefinition)columnDefinitions[columnIndex].Clone(); oldColumnDefinitions[columnIndex] = (ColumnDefinition)columnDefinitions[columnIndex].Clone();
@@ -128,21 +153,20 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
} }
// What is the cleanest way to do this? Add function to Generator? // What is the cleanest way to do this? Add function to Generator?
var quoter = new SQLiteQuoter(); var columnsToInsert = string.Join(", ", tableDefinition.Columns.Select(c => _quoter.QuoteColumnName(c.Name)));
var columnsToInsert = string.Join(", ", tableDefinition.Columns.Select(c => quoter.QuoteColumnName(c.Name))); var columnsToFetch = string.Join(", ", (oldColumnDefinitions ?? tableDefinition.Columns).Select(c => _quoter.QuoteColumnName(c.Name)));
var columnsToFetch = string.Join(", ", (oldColumnDefinitions ?? tableDefinition.Columns).Select(c => quoter.QuoteColumnName(c.Name)));
Process(new CreateTableExpression() { TableName = tempTableName, Columns = tableDefinition.Columns.ToList() }); Process(new CreateTableExpression { TableName = tempTableName, Columns = tableDefinition.Columns.ToList() });
Process(string.Format("INSERT INTO {0} ({1}) SELECT {2} FROM {3}", quoter.QuoteTableName(tempTableName), columnsToInsert, columnsToFetch, quoter.QuoteTableName(tableName))); Process($"INSERT INTO {_quoter.QuoteTableName(tempTableName)} ({columnsToInsert}) SELECT {columnsToFetch} FROM {_quoter.QuoteTableName(tableName)}");
Process(new DeleteTableExpression() { TableName = tableName }); Process(new DeleteTableExpression { TableName = tableName });
Process(new RenameTableExpression() { OldName = tempTableName, NewName = tableName }); Process(new RenameTableExpression { OldName = tempTableName, NewName = tableName });
foreach (var index in tableDefinition.Indexes) foreach (var index in tableDefinition.Indexes)
{ {
Process(new CreateIndexExpression() { Index = index }); Process(new CreateIndexExpression { Index = index });
} }
} }
} }

View File

@@ -0,0 +1,76 @@
using System.Data;
using FluentMigrator.Runner.Generators.Base;
using FluentMigrator.Runner.Generators.SQLite;
namespace NzbDrone.Core.Datastore.Migration.Framework;
// Based on https://github.com/fluentmigrator/fluentmigrator/blob/v6.2.0/src/FluentMigrator.Runner.SQLite/Generators/SQLite/SQLiteTypeMap.cs
public sealed class NzbDroneSQLiteTypeMap : TypeMapBase, ISQLiteTypeMap
{
public bool UseStrictTables { get; }
public NzbDroneSQLiteTypeMap(bool useStrictTables = false)
{
UseStrictTables = useStrictTables;
SetupTypeMaps();
}
// Must be kept in sync with upstream
protected override void SetupTypeMaps()
{
SetTypeMap(DbType.Binary, "BLOB");
SetTypeMap(DbType.Byte, "INTEGER");
SetTypeMap(DbType.Int16, "INTEGER");
SetTypeMap(DbType.Int32, "INTEGER");
SetTypeMap(DbType.Int64, "INTEGER");
SetTypeMap(DbType.SByte, "INTEGER");
SetTypeMap(DbType.UInt16, "INTEGER");
SetTypeMap(DbType.UInt32, "INTEGER");
SetTypeMap(DbType.UInt64, "INTEGER");
if (!UseStrictTables)
{
SetTypeMap(DbType.Currency, "NUMERIC");
SetTypeMap(DbType.Decimal, "NUMERIC");
SetTypeMap(DbType.Double, "NUMERIC");
SetTypeMap(DbType.Single, "NUMERIC");
SetTypeMap(DbType.VarNumeric, "NUMERIC");
SetTypeMap(DbType.Date, "DATETIME");
SetTypeMap(DbType.DateTime, "DATETIME");
SetTypeMap(DbType.DateTime2, "DATETIME");
SetTypeMap(DbType.Time, "DATETIME");
SetTypeMap(DbType.Guid, "UNIQUEIDENTIFIER");
// Custom so that we can use DateTimeOffset in Postgres for appropriate DB typing
SetTypeMap(DbType.DateTimeOffset, "DATETIME");
}
else
{
SetTypeMap(DbType.Currency, "TEXT");
SetTypeMap(DbType.Decimal, "TEXT");
SetTypeMap(DbType.Double, "REAL");
SetTypeMap(DbType.Single, "REAL");
SetTypeMap(DbType.VarNumeric, "TEXT");
SetTypeMap(DbType.Date, "TEXT");
SetTypeMap(DbType.DateTime, "TEXT");
SetTypeMap(DbType.DateTime2, "TEXT");
SetTypeMap(DbType.Time, "TEXT");
SetTypeMap(DbType.Guid, "TEXT");
// Custom so that we can use DateTimeOffset in Postgres for appropriate DB typing
SetTypeMap(DbType.DateTimeOffset, "TEXT");
}
SetTypeMap(DbType.AnsiString, "TEXT");
SetTypeMap(DbType.String, "TEXT");
SetTypeMap(DbType.AnsiStringFixedLength, "TEXT");
SetTypeMap(DbType.StringFixedLength, "TEXT");
SetTypeMap(DbType.Boolean, "INTEGER");
}
public override string GetTypeMap(DbType type, int? size, int? precision)
{
return base.GetTypeMap(type, size: null, precision: null);
}
}

View File

@@ -669,7 +669,7 @@ namespace NzbDrone.Core.Indexers.Definitions
{ {
var advancedSeasonRegex = new Regex(@"\b(?:(?<season>\d+)(?:st|nd|rd|th) Season|Season (?<season>\d+))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); var advancedSeasonRegex = new Regex(@"\b(?:(?<season>\d+)(?:st|nd|rd|th) Season|Season (?<season>\d+))\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);
var seasonCharactersRegex = new Regex(@"(I{2,})$", RegexOptions.Compiled); var seasonCharactersRegex = new Regex(@"(I{2,})$", RegexOptions.Compiled);
var seasonNumberRegex = new Regex(@"\b(?<!(Part|No\.)[- ._])(?<!\d[/])(?<!\#)(?:S)?(?<season>[2-9])$", RegexOptions.Compiled); var seasonNumberRegex = new Regex(@"\b(?<!Part[- ._])(?<!\d[/])(?:S)?(?<season>[2-9])$", RegexOptions.Compiled);
foreach (var title in titles) foreach (var title in titles)
{ {

View File

@@ -69,8 +69,8 @@ public class Shazbat : TorrentIndexerBase<ShazbatSettings>
.AddFormParameter("referer", "") .AddFormParameter("referer", "")
.AddFormParameter("query", "") .AddFormParameter("query", "")
.AddFormParameter("tv_timezone", "0") .AddFormParameter("tv_timezone", "0")
.AddFormParameter("username", Settings.Username) .AddFormParameter("tv_login", Settings.Username)
.AddFormParameter("password", Settings.Password) .AddFormParameter("tv_password", Settings.Password)
.SetHeader("Content-Type", "application/x-www-form-urlencoded") .SetHeader("Content-Type", "application/x-www-form-urlencoded")
.SetHeader("Referer", loginUrl) .SetHeader("Referer", loginUrl)
.Build(); .Build();
@@ -92,9 +92,9 @@ public class Shazbat : TorrentIndexerBase<ShazbatSettings>
_logger.Debug("Authentication succeeded."); _logger.Debug("Authentication succeeded.");
} }
protected override bool CheckIfLoginNeeded(HttpResponse httpResponse) protected override bool CheckIfLoginNeeded(HttpResponse response)
{ {
return (httpResponse.HasHttpRedirect && httpResponse.RedirectUrl.ContainsIgnoreCase("login")) || httpResponse.Content.ContainsIgnoreCase("sign in now"); return response.Content.ContainsIgnoreCase("sign in now");
} }
private IndexerCapabilities SetCapabilities() private IndexerCapabilities SetCapabilities()
@@ -202,7 +202,7 @@ public class ShazbatRequestGenerator : IIndexerRequestGenerator
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }
} }
public partial class ShazbatParser : IParseIndexerResponse public class ShazbatParser : IParseIndexerResponse
{ {
private readonly ProviderDefinition _definition; private readonly ProviderDefinition _definition;
private readonly ShazbatSettings _settings; private readonly ShazbatSettings _settings;
@@ -210,10 +210,8 @@ public partial class ShazbatParser : IParseIndexerResponse
private readonly IIndexerHttpClient _httpClient; private readonly IIndexerHttpClient _httpClient;
private readonly Logger _logger; private readonly Logger _logger;
private readonly HashSet<string> _hdResolutions = ["1080p", "1080i", "720p"]; private readonly Regex _torrentInfoRegex = new(@"\((?<size>\d+)\):(?<seeders>\d+) \/ :(?<leechers>\d+)$", RegexOptions.Compiled);
private readonly HashSet<string> _hdResolutions = new() { "1080p", "1080i", "720p" };
[GeneratedRegex(@"\((?<size>\d+)\)\s*:(?<seeders>\d+) \/ :(?<leechers>\d+)$", RegexOptions.Compiled)]
private static partial Regex TorrentInfoRegex();
public ShazbatParser(ProviderDefinition definition, ShazbatSettings settings, TimeSpan rateLimit, IIndexerHttpClient httpClient, Logger logger) public ShazbatParser(ProviderDefinition definition, ShazbatSettings settings, TimeSpan rateLimit, IIndexerHttpClient httpClient, Logger logger)
{ {
@@ -280,8 +278,7 @@ public partial class ShazbatParser : IParseIndexerResponse
var releaseRequest = new IndexerRequest(showRequest); var releaseRequest = new IndexerRequest(showRequest);
var releaseResponse = new IndexerResponse(releaseRequest, _httpClient.ExecuteProxied(releaseRequest.HttpRequest, _definition)); var releaseResponse = new IndexerResponse(releaseRequest, _httpClient.ExecuteProxied(releaseRequest.HttpRequest, _definition));
if ((releaseResponse.HttpResponse.HasHttpRedirect && releaseResponse.HttpResponse.RedirectUrl.ContainsIgnoreCase("login")) || if (releaseResponse.HttpResponse.Content.ContainsIgnoreCase("sign in now"))
releaseResponse.HttpResponse.Content.ContainsIgnoreCase("sign in now"))
{ {
// Remove cookie cache // Remove cookie cache
CookiesUpdater(null, null); CookiesUpdater(null, null);
@@ -327,15 +324,13 @@ public partial class ShazbatParser : IParseIndexerResponse
var title = ParseTitle(row.QuerySelector("td:nth-of-type(3)")); var title = ParseTitle(row.QuerySelector("td:nth-of-type(3)"));
var infoString = row.QuerySelector("td:nth-of-type(4)")?.TextContent.Trim() ?? string.Empty; var infoString = row.QuerySelector("td:nth-of-type(4)")?.TextContent.Trim() ?? string.Empty;
var matchInfo = TorrentInfoRegex().Match(infoString); var matchInfo = _torrentInfoRegex.Match(infoString);
var size = matchInfo.Groups["size"].Success && long.TryParse(matchInfo.Groups["size"].Value, out var outSize) ? outSize : 0; var size = matchInfo.Groups["size"].Success && long.TryParse(matchInfo.Groups["size"].Value, out var outSize) ? outSize : 0;
var seeders = matchInfo.Groups["seeders"].Success && int.TryParse(matchInfo.Groups["seeders"].Value, out var outSeeders) ? outSeeders : 0; var seeders = matchInfo.Groups["seeders"].Success && int.TryParse(matchInfo.Groups["seeders"].Value, out var outSeeders) ? outSeeders : 0;
var leechers = matchInfo.Groups["leechers"].Success && int.TryParse(matchInfo.Groups["leechers"].Value, out var outLeechers) ? outLeechers : 0; var leechers = matchInfo.Groups["leechers"].Success && int.TryParse(matchInfo.Groups["leechers"].Value, out var outLeechers) ? outLeechers : 0;
var dateTimestamp = row.QuerySelector(".datetime[data-timestamp]")?.GetAttribute("data-timestamp"); var dateTimestamp = row.QuerySelector(".datetime[data-timestamp]")?.GetAttribute("data-timestamp");
publishDate = dateTimestamp != null && ParseUtil.TryCoerceLong(dateTimestamp, out var timestamp) publishDate = dateTimestamp != null && ParseUtil.TryCoerceDouble(dateTimestamp, out var timestamp) ? DateTimeUtil.UnixTimestampToDateTime(timestamp) : publishDate.AddMinutes(-1);
? DateTimeUtil.UnixTimestampToDateTime(timestamp)
: publishDate.AddMinutes(-1);
var release = new TorrentInfo var release = new TorrentInfo
{ {
@@ -369,10 +364,10 @@ public partial class ShazbatParser : IParseIndexerResponse
return title?.TextContent.Trim(); return title?.TextContent.Trim();
} }
private List<IndexerCategory> ParseCategories(string title) protected virtual List<IndexerCategory> ParseCategories(string title)
{ {
return var categories = new List<IndexerCategory>
[ {
NewznabStandardCategory.TV, NewznabStandardCategory.TV,
title switch title switch
{ {
@@ -380,7 +375,9 @@ public partial class ShazbatParser : IParseIndexerResponse
_ when title.Contains("2160p") => NewznabStandardCategory.TVUHD, _ when title.Contains("2160p") => NewznabStandardCategory.TVUHD,
_ => NewznabStandardCategory.TVSD _ => NewznabStandardCategory.TVSD
} }
]; };
return categories;
} }
public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; } public Action<IDictionary<string, string>, DateTime?> CookiesUpdater { get; set; }

View File

@@ -13,9 +13,9 @@
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" /> <PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageReference Include="Npgsql" Version="9.0.3" /> <PackageReference Include="Npgsql" Version="9.0.3" />
<PackageReference Include="Polly" Version="8.6.4" /> <PackageReference Include="Polly" Version="8.6.4" />
<PackageReference Include="Servarr.FluentMigrator.Runner" Version="3.3.2.9" /> <PackageReference Include="FluentMigrator.Runner" Version="6.2.0" />
<PackageReference Include="Servarr.FluentMigrator.Runner.Postgres" Version="3.3.2.9" /> <PackageReference Include="FluentMigrator.Runner.Postgres" Version="6.2.0" />
<PackageReference Include="Servarr.FluentMigrator.Runner.SQLite" Version="3.3.2.9" /> <PackageReference Include="FluentMigrator.Runner.SQLite" Version="6.2.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.19" /> <PackageReference Include="System.Drawing.Common" Version="8.0.19" />
<PackageReference Include="System.Memory" Version="4.6.3" /> <PackageReference Include="System.Memory" Version="4.6.3" />
<PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" /> <PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />

View File

@@ -64,8 +64,6 @@ namespace NzbDrone.Host
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8)); options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12)); options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16)); options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16));
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("fc00::"), 7));
options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("fe80::"), 10));
}); });
services.AddRouting(options => options.LowercaseUrls = true); services.AddRouting(options => options.LowercaseUrls = true);