mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-18 21:34:28 -04:00
Compare commits
16 Commits
sonarr-pul
...
v0.4.1.264
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9312f17041 | ||
|
|
8192c22910 | ||
|
|
0b1d6b677a | ||
|
|
d666df0189 | ||
|
|
10d8f345c1 | ||
|
|
fb720b8714 | ||
|
|
e8131b5791 | ||
|
|
4f793f6b93 | ||
|
|
4215c21c94 | ||
|
|
6913789adc | ||
|
|
09e0c40792 | ||
|
|
baff805551 | ||
|
|
c885fe43cd | ||
|
|
464a777722 | ||
|
|
89e5999c85 | ||
|
|
b6fa332550 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -120,6 +120,7 @@ _artifacts
|
|||||||
_rawPackage/
|
_rawPackage/
|
||||||
_dotTrace*
|
_dotTrace*
|
||||||
_tests/
|
_tests/
|
||||||
|
_temp*
|
||||||
*.Result.xml
|
*.Result.xml
|
||||||
coverage*.xml
|
coverage*.xml
|
||||||
coverage*.json
|
coverage*.json
|
||||||
|
|||||||
@@ -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: '0.4.0'
|
majorVersion: '0.4.1'
|
||||||
minorVersion: $[counter('minorVersion', 1)]
|
minorVersion: $[counter('minorVersion', 1)]
|
||||||
readarrVersion: '$(majorVersion).$(minorVersion)'
|
readarrVersion: '$(majorVersion).$(minorVersion)'
|
||||||
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
buildName: '$(Build.SourceBranchName).$(readarrVersion)'
|
||||||
@@ -20,7 +20,7 @@ variables:
|
|||||||
innoVersion: '6.2.0'
|
innoVersion: '6.2.0'
|
||||||
windowsImage: 'windows-2022'
|
windowsImage: 'windows-2022'
|
||||||
linuxImage: 'ubuntu-20.04'
|
linuxImage: 'ubuntu-20.04'
|
||||||
macImage: 'macOS-12'
|
macImage: 'macOS-13'
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branches:
|
branches:
|
||||||
|
|||||||
2
frontend/.vscode/settings.json
vendored
2
frontend/.vscode/settings.json
vendored
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll": true
|
"source.fixAll": "explicit"
|
||||||
},
|
},
|
||||||
|
|
||||||
"typescript.preferences.quoteStyle": "single",
|
"typescript.preferences.quoteStyle": "single",
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
|
||||||
|
|
||||||
.isDisabled {
|
&.isDisabled {
|
||||||
color: var(--disabledColor);
|
color: var(--disabledColor);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
@@ -15,11 +14,11 @@ function createMapStateToProps() {
|
|||||||
(state) => state.settings.advancedSettings,
|
(state) => state.settings.advancedSettings,
|
||||||
(state) => state.settings.namingExamples,
|
(state) => state.settings.namingExamples,
|
||||||
createSettingsSectionSelector(SECTION),
|
createSettingsSectionSelector(SECTION),
|
||||||
(advancedSettings, examples, sectionSettings) => {
|
(advancedSettings, namingExamples, sectionSettings) => {
|
||||||
return {
|
return {
|
||||||
advancedSettings,
|
advancedSettings,
|
||||||
examples: examples.item,
|
examples: namingExamples.item,
|
||||||
examplesPopulated: !_.isEmpty(examples.item),
|
examplesPopulated: namingExamples.isPopulated,
|
||||||
...sectionSettings
|
...sectionSettings
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<PackageVersion Include="AutoFixture" Version="4.17.0" />
|
<PackageVersion Include="AutoFixture" Version="4.17.0" />
|
||||||
<PackageVersion Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" PrivateAssets="all" />
|
<PackageVersion Include="coverlet.collector" Version="3.0.4-preview.27.ge7cb7c3b40" PrivateAssets="all" />
|
||||||
<PackageVersion Include="Dapper" Version="2.0.151" />
|
<PackageVersion Include="Dapper" Version="2.0.151" />
|
||||||
|
<PackageVersion Include="Diacritical.Net" Version="1.0.4" />
|
||||||
<PackageVersion Include="DryIoc.dll" Version="5.4.3" />
|
<PackageVersion Include="DryIoc.dll" Version="5.4.3" />
|
||||||
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
|
||||||
<PackageVersion Include="Equ" Version="2.3.0" />
|
<PackageVersion Include="Equ" Version="2.3.0" />
|
||||||
@@ -65,4 +66,4 @@
|
|||||||
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
|
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
|
||||||
<PackageVersion Include="TagLibSharp-Lidarr" Version="2.2.0.19" />
|
<PackageVersion Include="TagLibSharp-Lidarr" Version="2.2.0.19" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -89,6 +89,10 @@ namespace NzbDrone.Common.Test.InstrumentationTests
|
|||||||
[TestCase(@"https://discord.com/api/webhooks/mySecret")]
|
[TestCase(@"https://discord.com/api/webhooks/mySecret")]
|
||||||
[TestCase(@"https://discord.com/api/webhooks/mySecret/01233210")]
|
[TestCase(@"https://discord.com/api/webhooks/mySecret/01233210")]
|
||||||
|
|
||||||
|
// Telegram
|
||||||
|
[TestCase(@"https://api.telegram.org/bot1234567890:mySecret/sendmessage: chat_id=123456&parse_mode=HTML&text=<text>")]
|
||||||
|
[TestCase(@"https://api.telegram.org/bot1234567890:mySecret/")]
|
||||||
|
|
||||||
public void should_clean_message(string message)
|
public void should_clean_message(string message)
|
||||||
{
|
{
|
||||||
var cleansedMessage = CleanseLogMessage.Cleanse(message);
|
var cleansedMessage = CleanseLogMessage.Cleanse(message);
|
||||||
|
|||||||
@@ -54,7 +54,10 @@ namespace NzbDrone.Common.Instrumentation
|
|||||||
new (@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
new (@"api/v[0-9]/notification/readarr/(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
// Discord
|
// Discord
|
||||||
new (@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase)
|
new (@"discord.com/api/webhooks/((?<secret>[\w-]+)/)?(?<secret>[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
|
||||||
|
|
||||||
|
// Telegram
|
||||||
|
new (@"api.telegram.org/bot(?<id>[\d]+):(?<secret>[\w-]+)/", RegexOptions.Compiled | RegexOptions.IgnoreCase)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Regex CleanseRemoteIPRegex = new (@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);
|
private static readonly Regex CleanseRemoteIPRegex = new (@"(?:Auth-\w+(?<!Failure|Unauthorized) ip|from) (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", RegexOptions.Compiled);
|
||||||
|
|||||||
@@ -49,10 +49,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void magnet_download_should_not_return_the_item()
|
public void magnet_download_should_be_returned_as_queued()
|
||||||
{
|
{
|
||||||
PrepareClientToReturnMagnetItem();
|
PrepareClientToReturnMagnetItem();
|
||||||
Subject.GetItems().Count().Should().Be(0);
|
|
||||||
|
var item = Subject.GetItems().Single();
|
||||||
|
|
||||||
|
item.Status.Should().Be(DownloadItemStatus.Queued);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
|
|||||||
public void magnet_download_should_not_return_the_item()
|
public void magnet_download_should_not_return_the_item()
|
||||||
{
|
{
|
||||||
PrepareClientToReturnMagnetItem();
|
PrepareClientToReturnMagnetItem();
|
||||||
Subject.GetItems().Count().Should().Be(0);
|
|
||||||
|
var item = Subject.GetItems().Single();
|
||||||
|
|
||||||
|
item.Status.Should().Be(DownloadItemStatus.Queued);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using NzbDrone.Core.Test.Framework;
|
|||||||
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class BookInfoProxyFixture : CoreTest<BookInfoProxy>
|
public class BookInfoProxyFixture : CoreTest<BookInfoProxy>
|
||||||
{
|
{
|
||||||
private MetadataProfile _metadataProfile;
|
private MetadataProfile _metadataProfile;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using NzbDrone.Test.Common;
|
|||||||
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
namespace NzbDrone.Core.Test.MetadataSource.Goodreads
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class BookInfoProxySearchFixture : CoreTest<BookInfoProxy>
|
public class BookInfoProxySearchFixture : CoreTest<BookInfoProxy>
|
||||||
{
|
{
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
|||||||
@@ -41,12 +41,6 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
|
|
||||||
foreach (var torrent in torrents)
|
foreach (var torrent in torrents)
|
||||||
{
|
{
|
||||||
// If totalsize == 0 the torrent is a magnet downloading metadata
|
|
||||||
if (torrent.TotalSize == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var outputPath = new OsPath(torrent.DownloadDir);
|
var outputPath = new OsPath(torrent.DownloadDir);
|
||||||
|
|
||||||
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
|
if (Settings.TvDirectory.IsNotNullOrWhiteSpace())
|
||||||
@@ -97,6 +91,10 @@ namespace NzbDrone.Core.Download.Clients.Transmission
|
|||||||
item.Status = DownloadItemStatus.Warning;
|
item.Status = DownloadItemStatus.Warning;
|
||||||
item.Message = torrent.ErrorString;
|
item.Message = torrent.ErrorString;
|
||||||
}
|
}
|
||||||
|
else if (torrent.TotalSize == 0)
|
||||||
|
{
|
||||||
|
item.Status = DownloadItemStatus.Queued;
|
||||||
|
}
|
||||||
else if (torrent.LeftUntilDone == 0 && (torrent.Status == TransmissionTorrentStatus.Stopped ||
|
else if (torrent.LeftUntilDone == 0 && (torrent.Status == TransmissionTorrentStatus.Stopped ||
|
||||||
torrent.Status == TransmissionTorrentStatus.Seeding ||
|
torrent.Status == TransmissionTorrentStatus.Seeding ||
|
||||||
torrent.Status == TransmissionTorrentStatus.SeedingWait))
|
torrent.Status == TransmissionTorrentStatus.SeedingWait))
|
||||||
|
|||||||
@@ -25,15 +25,15 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnGrab(GrabMessage message)
|
public override void OnGrab(GrabMessage message)
|
||||||
{
|
{
|
||||||
var embeds = new List<Embed>
|
var embeds = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Description = message.Message,
|
Description = message.Message,
|
||||||
Title = message.Author.Name,
|
Title = message.Author.Name,
|
||||||
Text = message.Message,
|
Text = message.Message,
|
||||||
Color = (int)DiscordColors.Warning
|
Color = (int)DiscordColors.Warning
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var payload = CreatePayload($"Grabbed: {message.Message}", embeds);
|
var payload = CreatePayload($"Grabbed: {message.Message}", embeds);
|
||||||
|
|
||||||
_proxy.SendPayload(payload, Settings);
|
_proxy.SendPayload(payload, Settings);
|
||||||
@@ -43,7 +43,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Description = message.Message,
|
Description = message.Message,
|
||||||
Title = message.Author.Name,
|
Title = message.Author.Name,
|
||||||
@@ -59,12 +59,12 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnRename(Author author, List<RenamedBookFile> renamedFiles)
|
public override void OnRename(Author author, List<RenamedBookFile> renamedFiles)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = author.Name,
|
Title = author.Name,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload("Renamed", attachments);
|
var payload = CreatePayload("Renamed", attachments);
|
||||||
|
|
||||||
@@ -74,21 +74,21 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnAuthorAdded(Author author)
|
public override void OnAuthorAdded(Author author)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = author.Name,
|
Title = author.Name,
|
||||||
Fields = new List<DiscordField>()
|
Fields = new List<DiscordField>()
|
||||||
{
|
{
|
||||||
new DiscordField()
|
new ()
|
||||||
{
|
{
|
||||||
Name = "Links",
|
Name = "Links",
|
||||||
Value = string.Join(" / ", author.Metadata.Value.Links.Select(link => $"[{link.Name}]({link.Url})"))
|
Value = string.Join(" / ", author.Metadata.Value.Links.Select(link => $"[{link.Name}]({link.Url})"))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var payload = CreatePayload($"Author Added", attachments);
|
var payload = CreatePayload("Author Added", attachments);
|
||||||
|
|
||||||
_proxy.SendPayload(payload, Settings);
|
_proxy.SendPayload(payload, Settings);
|
||||||
}
|
}
|
||||||
@@ -96,13 +96,13 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage)
|
public override void OnAuthorDelete(AuthorDeleteMessage deleteMessage)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = deleteMessage.Author.Name,
|
Title = deleteMessage.Author.Name,
|
||||||
Description = deleteMessage.DeletedFilesMessage
|
Description = deleteMessage.DeletedFilesMessage
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload("Author Deleted", attachments);
|
var payload = CreatePayload("Author Deleted", attachments);
|
||||||
|
|
||||||
@@ -112,13 +112,13 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnBookDelete(BookDeleteMessage deleteMessage)
|
public override void OnBookDelete(BookDeleteMessage deleteMessage)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = $"${deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title}",
|
Title = $"{deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title}",
|
||||||
Description = deleteMessage.DeletedFilesMessage
|
Description = deleteMessage.DeletedFilesMessage
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload("Book Deleted", attachments);
|
var payload = CreatePayload("Book Deleted", attachments);
|
||||||
|
|
||||||
@@ -128,13 +128,13 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage)
|
public override void OnBookFileDelete(BookFileDeleteMessage deleteMessage)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = $"${deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title} - file deleted",
|
Title = $"{deleteMessage.Book.Author.Value.Name} - ${deleteMessage.Book.Title} - file deleted",
|
||||||
Description = deleteMessage.BookFile.Path
|
Description = deleteMessage.BookFile.Path
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload("Book File Deleted", attachments);
|
var payload = CreatePayload("Book File Deleted", attachments);
|
||||||
|
|
||||||
@@ -144,14 +144,14 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
|
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = healthCheck.Source.Name,
|
Title = healthCheck.Source.Name,
|
||||||
Text = healthCheck.Message,
|
Text = healthCheck.Message,
|
||||||
Color = healthCheck.Type == HealthCheck.HealthCheckResult.Warning ? (int)DiscordColors.Warning : (int)DiscordColors.Danger
|
Color = healthCheck.Type == HealthCheck.HealthCheckResult.Warning ? (int)DiscordColors.Warning : (int)DiscordColors.Danger
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload("Health Issue", attachments);
|
var payload = CreatePayload("Health Issue", attachments);
|
||||||
|
|
||||||
@@ -161,13 +161,13 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnBookRetag(BookRetagMessage message)
|
public override void OnBookRetag(BookRetagMessage message)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Title = BOOK_RETAGGED_TITLE,
|
Title = BOOK_RETAGGED_TITLE,
|
||||||
Text = message.Message
|
Text = message.Message
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload($"Track file tags updated: {message.Message}", attachments);
|
var payload = CreatePayload($"Track file tags updated: {message.Message}", attachments);
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Description = message.Message,
|
Description = message.Message,
|
||||||
Title = message.SourceTitle,
|
Title = message.SourceTitle,
|
||||||
@@ -195,7 +195,7 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Description = message.Message,
|
Description = message.Message,
|
||||||
Title = message.Book?.Title ?? message.Message,
|
Title = message.Book?.Title ?? message.Message,
|
||||||
@@ -211,32 +211,32 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||||||
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
|
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
|
||||||
{
|
{
|
||||||
var attachments = new List<Embed>
|
var attachments = new List<Embed>
|
||||||
{
|
{
|
||||||
new Embed
|
new ()
|
||||||
{
|
{
|
||||||
Author = new DiscordAuthor
|
Author = new DiscordAuthor
|
||||||
{
|
{
|
||||||
Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author,
|
Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author,
|
||||||
IconUrl = "https://raw.githubusercontent.com/Readarr/Readarr/develop/Logo/256.png"
|
IconUrl = "https://raw.githubusercontent.com/Readarr/Readarr/develop/Logo/256.png"
|
||||||
},
|
},
|
||||||
Title = APPLICATION_UPDATE_TITLE,
|
Title = APPLICATION_UPDATE_TITLE,
|
||||||
Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
|
Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
|
||||||
Color = (int)DiscordColors.Standard,
|
Color = (int)DiscordColors.Standard,
|
||||||
Fields = new List<DiscordField>()
|
Fields = new List<DiscordField>()
|
||||||
{
|
{
|
||||||
new DiscordField()
|
new ()
|
||||||
{
|
{
|
||||||
Name = "Previous Version",
|
Name = "Previous Version",
|
||||||
Value = updateMessage.PreviousVersion.ToString()
|
Value = updateMessage.PreviousVersion.ToString()
|
||||||
},
|
},
|
||||||
new DiscordField()
|
new ()
|
||||||
{
|
{
|
||||||
Name = "New Version",
|
Name = "New Version",
|
||||||
Value = updateMessage.NewVersion.ToString()
|
Value = updateMessage.NewVersion.ToString()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = CreatePayload(null, attachments);
|
var payload = CreatePayload(null, attachments);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapper" />
|
<PackageReference Include="Dapper" />
|
||||||
|
<PackageReference Include="Diacritical.Net" />
|
||||||
<PackageReference Include="LazyCache" />
|
<PackageReference Include="LazyCache" />
|
||||||
<PackageReference Include="Polly" />
|
<PackageReference Include="Polly" />
|
||||||
<PackageReference Include="System.Text.Json" />
|
<PackageReference Include="System.Text.Json" />
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ namespace NzbDrone.Host
|
|||||||
Name = "apikey",
|
Name = "apikey",
|
||||||
Type = SecuritySchemeType.ApiKey,
|
Type = SecuritySchemeType.ApiKey,
|
||||||
Scheme = "apiKey",
|
Scheme = "apiKey",
|
||||||
Description = "Apikey passed as header",
|
Description = "Apikey passed as query parameter",
|
||||||
In = ParameterLocation.Query,
|
In = ParameterLocation.Query,
|
||||||
Reference = new OpenApiReference
|
Reference = new OpenApiReference
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Readarr.Api.V1.Author;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests
|
namespace NzbDrone.Integration.Test.ApiTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class AuthorEditorFixture : IntegrationTest
|
public class AuthorEditorFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
private void GivenExistingAuthor()
|
private void GivenExistingAuthor()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using NUnit.Framework;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests
|
namespace NzbDrone.Integration.Test.ApiTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class AuthorFixture : IntegrationTest
|
public class AuthorFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using NUnit.Framework;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests
|
namespace NzbDrone.Integration.Test.ApiTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class AuthorLookupFixture : IntegrationTest
|
public class AuthorLookupFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
[TestCase("Robert Harris", "Robert Harris")]
|
[TestCase("Robert Harris", "Robert Harris")]
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using Readarr.Api.V1.Blocklist;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests
|
namespace NzbDrone.Integration.Test.ApiTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class BlocklistFixture : IntegrationTest
|
public class BlocklistFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
private AuthorResource _author;
|
private AuthorResource _author;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using Readarr.Api.V1.Books;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests
|
namespace NzbDrone.Integration.Test.ApiTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class CalendarFixture : IntegrationTest
|
public class CalendarFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
public ClientBase<BookResource> Calendar;
|
public ClientBase<BookResource> Calendar;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using Readarr.Api.V1.RootFolders;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests.WantedTests
|
namespace NzbDrone.Integration.Test.ApiTests.WantedTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class CutoffUnmetFixture : IntegrationTest
|
public class CutoffUnmetFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using Readarr.Api.V1.RootFolders;
|
|||||||
namespace NzbDrone.Integration.Test.ApiTests.WantedTests
|
namespace NzbDrone.Integration.Test.ApiTests.WantedTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Ignore("Waiting for metadata to be back again", Until = "2024-08-15 00:00:00Z")]
|
[Ignore("Waiting for metadata to be back again", Until = "2024-12-15 00:00:00Z")]
|
||||||
public class MissingFixture : IntegrationTest
|
public class MissingFixture : IntegrationTest
|
||||||
{
|
{
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
|||||||
@@ -13815,7 +13815,7 @@
|
|||||||
},
|
},
|
||||||
"apikey": {
|
"apikey": {
|
||||||
"type": "apiKey",
|
"type": "apiKey",
|
||||||
"description": "Apikey passed as header",
|
"description": "Apikey passed as query parameter",
|
||||||
"name": "apikey",
|
"name": "apikey",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Diacritical;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NzbDrone.Core.Authentication;
|
using NzbDrone.Core.Authentication;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
namespace Readarr.Http.Authentication
|
namespace Readarr.Http.Authentication
|
||||||
{
|
{
|
||||||
public static class AuthenticationBuilderExtensions
|
public static class AuthenticationBuilderExtensions
|
||||||
{
|
{
|
||||||
|
private static readonly Regex CookieNameRegex = new Regex(@"[^a-z0-9]+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder authenticationBuilder, string name, Action<ApiKeyAuthenticationOptions> options)
|
public static AuthenticationBuilder AddApiKey(this AuthenticationBuilder authenticationBuilder, string name, Action<ApiKeyAuthenticationOptions> options)
|
||||||
{
|
{
|
||||||
return authenticationBuilder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(name, options);
|
return authenticationBuilder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(name, options);
|
||||||
@@ -29,19 +35,27 @@ namespace Readarr.Http.Authentication
|
|||||||
|
|
||||||
public static AuthenticationBuilder AddAppAuthentication(this IServiceCollection services)
|
public static AuthenticationBuilder AddAppAuthentication(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
return services.AddAuthentication()
|
services.AddOptions<CookieAuthenticationOptions>(AuthenticationType.Forms.ToString())
|
||||||
.AddNone(AuthenticationType.None.ToString())
|
.Configure<IConfigFileProvider>((options, configFileProvider) =>
|
||||||
.AddExternal(AuthenticationType.External.ToString())
|
|
||||||
.AddBasic(AuthenticationType.Basic.ToString())
|
|
||||||
.AddCookie(AuthenticationType.Forms.ToString(), options =>
|
|
||||||
{
|
{
|
||||||
options.Cookie.Name = "ReadarrAuth";
|
// Replace diacritics and replace non-word characters to ensure cookie name doesn't contain any valid URL characters not allowed in cookie names
|
||||||
|
var instanceName = configFileProvider.InstanceName;
|
||||||
|
instanceName = instanceName.RemoveDiacritics();
|
||||||
|
instanceName = CookieNameRegex.Replace(instanceName, string.Empty);
|
||||||
|
|
||||||
|
options.Cookie.Name = $"{instanceName}Auth";
|
||||||
options.AccessDeniedPath = "/login?loginFailed=true";
|
options.AccessDeniedPath = "/login?loginFailed=true";
|
||||||
options.LoginPath = "/login";
|
options.LoginPath = "/login";
|
||||||
options.ExpireTimeSpan = TimeSpan.FromDays(7);
|
options.ExpireTimeSpan = TimeSpan.FromDays(7);
|
||||||
options.SlidingExpiration = true;
|
options.SlidingExpiration = true;
|
||||||
options.ReturnUrlParameter = "returnUrl";
|
options.ReturnUrlParameter = "returnUrl";
|
||||||
})
|
});
|
||||||
|
|
||||||
|
return services.AddAuthentication()
|
||||||
|
.AddNone(AuthenticationType.None.ToString())
|
||||||
|
.AddExternal(AuthenticationType.External.ToString())
|
||||||
|
.AddBasic(AuthenticationType.Basic.ToString())
|
||||||
|
.AddCookie(AuthenticationType.Forms.ToString())
|
||||||
.AddApiKey("API", options =>
|
.AddApiKey("API", options =>
|
||||||
{
|
{
|
||||||
options.HeaderName = "X-Api-Key";
|
options.HeaderName = "X-Api-Key";
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace Readarr.Http.Authentication
|
|||||||
|
|
||||||
await HttpContext.SignInAsync(AuthenticationType.Forms.ToString(), new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookies", "user", "identifier")), authProperties);
|
await HttpContext.SignInAsync(AuthenticationType.Forms.ToString(), new ClaimsPrincipal(new ClaimsIdentity(claims, "Cookies", "user", "identifier")), authProperties);
|
||||||
|
|
||||||
if (returnUrl.IsNullOrWhiteSpace())
|
if (returnUrl.IsNullOrWhiteSpace() || !Url.IsLocalUrl(returnUrl))
|
||||||
{
|
{
|
||||||
return Redirect(_configFileProvider.UrlBase + "/");
|
return Redirect(_configFileProvider.UrlBase + "/");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ namespace Readarr.Http.Middleware
|
|||||||
if (_urlBase.IsNotNullOrWhiteSpace() && context.Request.PathBase.Value.IsNullOrWhiteSpace())
|
if (_urlBase.IsNotNullOrWhiteSpace() && context.Request.PathBase.Value.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
context.Response.Redirect($"{_urlBase}{context.Request.Path}{context.Request.QueryString}");
|
context.Response.Redirect($"{_urlBase}{context.Request.Path}{context.Request.QueryString}");
|
||||||
|
context.Response.StatusCode = 307;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user