mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-05-24 02:02:29 -04:00
Merge remote-tracking branch 'jellyfinorigin/master' into feature/DatabaseRefactor
This commit is contained in:
commit
feea5af2f3
6
.github/workflows/ci-codeql-analysis.yml
vendored
6
.github/workflows/ci-codeql-analysis.yml
vendored
@ -27,11 +27,11 @@ jobs:
|
||||
dotnet-version: '9.0.x'
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-extended
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
|
||||
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
|
8
.github/workflows/ci-compat.yml
vendored
8
.github/workflows/ci-compat.yml
vendored
@ -26,7 +26,7 @@ jobs:
|
||||
dotnet build Jellyfin.Server -o ./out
|
||||
|
||||
- name: Upload Head
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
with:
|
||||
name: abi-head
|
||||
retention-days: 14
|
||||
@ -65,7 +65,7 @@ jobs:
|
||||
dotnet build Jellyfin.Server -o ./out
|
||||
|
||||
- name: Upload Head
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
with:
|
||||
name: abi-base
|
||||
retention-days: 14
|
||||
@ -85,13 +85,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Download abi-head
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
|
||||
with:
|
||||
name: abi-head
|
||||
path: abi-head
|
||||
|
||||
- name: Download abi-base
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
|
||||
with:
|
||||
name: abi-base
|
||||
path: abi-base
|
||||
|
16
.github/workflows/ci-openapi.yml
vendored
16
.github/workflows/ci-openapi.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
- name: Generate openapi.json
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||
- name: Upload openapi.json
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
with:
|
||||
name: openapi-head
|
||||
retention-days: 14
|
||||
@ -61,7 +61,7 @@ jobs:
|
||||
- name: Generate openapi.json
|
||||
run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
|
||||
- name: Upload openapi.json
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
with:
|
||||
name: openapi-base
|
||||
retention-days: 14
|
||||
@ -80,12 +80,12 @@ jobs:
|
||||
- openapi-base
|
||||
steps:
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
- name: Download openapi-base
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
|
||||
with:
|
||||
name: openapi-base
|
||||
path: openapi-base
|
||||
@ -158,7 +158,7 @@ jobs:
|
||||
run: |-
|
||||
echo "JELLYFIN_VERSION=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
@ -172,7 +172,7 @@ jobs:
|
||||
strip_components: 1
|
||||
target: "/srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
||||
- name: Move openapi.json (unstable) into place
|
||||
uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
|
||||
uses: appleboy/ssh-action@8faa84277b88b6cd1455986f459aa66cf72bc8a3 # v1.2.1
|
||||
with:
|
||||
host: "${{ secrets.REPO_HOST }}"
|
||||
username: "${{ secrets.REPO_USER }}"
|
||||
@ -220,7 +220,7 @@ jobs:
|
||||
run: |-
|
||||
echo "JELLYFIN_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
||||
- name: Download openapi-head
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4.1.9
|
||||
with:
|
||||
name: openapi-head
|
||||
path: openapi-head
|
||||
@ -234,7 +234,7 @@ jobs:
|
||||
strip_components: 1
|
||||
target: "/srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
||||
- name: Move openapi.json (stable) into place
|
||||
uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
|
||||
uses: appleboy/ssh-action@8faa84277b88b6cd1455986f459aa66cf72bc8a3 # v1.2.1
|
||||
with:
|
||||
host: "${{ secrets.REPO_HOST }}"
|
||||
username: "${{ secrets.REPO_USER }}"
|
||||
|
@ -79,7 +79,7 @@
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.2" />
|
||||
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="6.16.0" />
|
||||
<PackageVersion Include="z440.atl.core" Version="6.17.0" />
|
||||
<PackageVersion Include="TMDbLib" Version="2.2.0" />
|
||||
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
|
||||
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
|
||||
|
@ -204,7 +204,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
{
|
||||
if (_libraryManager.GetItemById(collectionId) is not BoxSet collection)
|
||||
{
|
||||
throw new ArgumentException("No collection exists with the supplied Id");
|
||||
throw new ArgumentException("No collection exists with the supplied collectionId " + collectionId);
|
||||
}
|
||||
|
||||
List<BaseItem>? itemList = null;
|
||||
@ -218,7 +218,7 @@ namespace Emby.Server.Implementations.Collections
|
||||
|
||||
if (item is null)
|
||||
{
|
||||
throw new ArgumentException("No item exists with the supplied Id");
|
||||
throw new ArgumentException("No item exists with the supplied Id " + id);
|
||||
}
|
||||
|
||||
if (!currentLinkedChildrenIds.Contains(id))
|
||||
|
@ -458,6 +458,7 @@ namespace Emby.Server.Implementations.Library
|
||||
foreach (var child in children)
|
||||
{
|
||||
_itemRepository.DeleteItem(child.Id);
|
||||
_cache.TryRemove(child.Id, out _);
|
||||
}
|
||||
|
||||
_cache.TryRemove(item.Id, out _);
|
||||
@ -2631,15 +2632,6 @@ namespace Emby.Server.Implementations.Library
|
||||
{
|
||||
episode.ParentIndexNumber = season.IndexNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Anime series don't generally have a season in their file name, however,
|
||||
TVDb needs a season to correctly get the metadata.
|
||||
Hence, a null season needs to be filled with something. */
|
||||
// FIXME perhaps this would be better for TVDb parser to ask for season 1 if no season is specified
|
||||
episode.ParentIndexNumber = 1;
|
||||
}
|
||||
|
||||
if (episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
|
@ -13,7 +13,7 @@
|
||||
"DeviceOnlineWithName": "{0} belépett",
|
||||
"FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet innen: {0}",
|
||||
"Favorites": "Kedvencek",
|
||||
"Folders": "Könyvtárak",
|
||||
"Folders": "Mappák",
|
||||
"Genres": "Műfajok",
|
||||
"HeaderAlbumArtists": "Albumelőadók",
|
||||
"HeaderContinueWatching": "Megtekintés folytatása",
|
||||
|
@ -58,8 +58,8 @@
|
||||
"NotificationOptionServerRestartRequired": "Riavvio del server necessario",
|
||||
"NotificationOptionTaskFailed": "Operazione pianificata fallita",
|
||||
"NotificationOptionUserLockedOut": "Utente bloccato",
|
||||
"NotificationOptionVideoPlayback": "La riproduzione video è iniziata",
|
||||
"NotificationOptionVideoPlaybackStopped": "La riproduzione video è stata interrotta",
|
||||
"NotificationOptionVideoPlayback": "Riproduzione video iniziata",
|
||||
"NotificationOptionVideoPlaybackStopped": "Riproduzione video interrotta",
|
||||
"Photos": "Foto",
|
||||
"Playlists": "Playlist",
|
||||
"Plugin": "Plugin",
|
||||
|
@ -116,6 +116,7 @@ public partial class AudioNormalizationTask : IScheduledTask
|
||||
{
|
||||
a.LUFS = await CalculateLUFSAsync(
|
||||
string.Format(CultureInfo.InvariantCulture, "-f concat -safe 0 -i \"{0}\"", tempFile),
|
||||
OperatingSystem.IsWindows(), // Wait for process to exit on Windows before we try deleting the concat file
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
@ -142,7 +143,10 @@ public partial class AudioNormalizationTask : IScheduledTask
|
||||
continue;
|
||||
}
|
||||
|
||||
t.LUFS = await CalculateLUFSAsync(string.Format(CultureInfo.InvariantCulture, "-i \"{0}\"", t.Path.Replace("\"", "\\\"", StringComparison.Ordinal)), cancellationToken).ConfigureAwait(false);
|
||||
t.LUFS = await CalculateLUFSAsync(
|
||||
string.Format(CultureInfo.InvariantCulture, "-i \"{0}\"", t.Path.Replace("\"", "\\\"", StringComparison.Ordinal)),
|
||||
false,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_itemRepository.SaveItems(tracks, cancellationToken);
|
||||
@ -162,7 +166,7 @@ public partial class AudioNormalizationTask : IScheduledTask
|
||||
];
|
||||
}
|
||||
|
||||
private async Task<float?> CalculateLUFSAsync(string inputArgs, CancellationToken cancellationToken)
|
||||
private async Task<float?> CalculateLUFSAsync(string inputArgs, bool waitForExit, CancellationToken cancellationToken)
|
||||
{
|
||||
var args = $"-hide_banner {inputArgs} -af ebur128=framelog=verbose -f null -";
|
||||
|
||||
@ -189,18 +193,28 @@ public partial class AudioNormalizationTask : IScheduledTask
|
||||
}
|
||||
|
||||
using var reader = process.StandardError;
|
||||
float? lufs = null;
|
||||
await foreach (var line in reader.ReadAllLinesAsync(cancellationToken))
|
||||
{
|
||||
Match match = LUFSRegex().Match(line);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
return float.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat);
|
||||
lufs = float.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture.NumberFormat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogError("Failed to find LUFS value in output");
|
||||
return null;
|
||||
if (lufs is null)
|
||||
{
|
||||
_logger.LogError("Failed to find LUFS value in output");
|
||||
}
|
||||
|
||||
if (waitForExit)
|
||||
{
|
||||
await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return lufs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,20 +212,4 @@ public class SystemController : BaseJellyfinApiController
|
||||
FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
return File(stream, "text/plain; charset=utf-8");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets wake on lan information.
|
||||
/// </summary>
|
||||
/// <response code="200">Information retrieved.</response>
|
||||
/// <returns>An <see cref="IEnumerable{WakeOnLanInfo}"/> with the WakeOnLan infos.</returns>
|
||||
[HttpGet("WakeOnLanInfo")]
|
||||
[Authorize]
|
||||
[Obsolete("This endpoint is obsolete.")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult<IEnumerable<WakeOnLanInfo>> GetWakeOnLanInfo()
|
||||
{
|
||||
var result = _networkManager.GetMacAddresses()
|
||||
.Select(i => new WakeOnLanInfo(i));
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||
// This is some regex that matches only on unicode "word" characters, as well as -, _ and @
|
||||
// In theory this will cut out most if not all 'control' characters which should help minimize any weirdness
|
||||
// Usernames can contain letters (a-z + whatever else unicode is cool with), numbers (0-9), at-signs (@), dashes (-), underscores (_), apostrophes ('), periods (.) and spaces ( )
|
||||
[GeneratedRegex(@"^[\w\ \-'._@+]+$")]
|
||||
[GeneratedRegex(@"^(?!\s)[\w\ \-'._@+]+(?<!\s)$")]
|
||||
private static partial Regex ValidUsernameRegex();
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -94,12 +94,6 @@ namespace MediaBrowser.Common.Net
|
||||
/// <returns>IP address to use, or loopback address if all else fails.</returns>
|
||||
string GetBindAddress(string source, out int? port);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all the MAC addresses associated with active interfaces.
|
||||
/// </summary>
|
||||
/// <returns>List of MAC addresses.</returns>
|
||||
IReadOnlyList<PhysicalAddress> GetMacAddresses();
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the address is part of the user defined LAN.
|
||||
/// </summary>
|
||||
|
@ -1203,6 +1203,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.Is4K.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.IsHD.HasValue)
|
||||
{
|
||||
return false;
|
||||
|
@ -84,6 +84,11 @@ namespace MediaBrowser.Model.Entities
|
||||
/// <summary>
|
||||
/// The TvMaze provider.
|
||||
/// </summary>
|
||||
TvMaze = 19
|
||||
TvMaze = 19,
|
||||
|
||||
/// <summary>
|
||||
/// The MusicBrainz recording provider.
|
||||
/// </summary>
|
||||
MusicBrainzRecording = 20,
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,11 @@ namespace MediaBrowser.Model.Providers
|
||||
/// <summary>
|
||||
/// A book.
|
||||
/// </summary>
|
||||
Book = 13
|
||||
Book = 13,
|
||||
|
||||
/// <summary>
|
||||
/// A music recording.
|
||||
/// </summary>
|
||||
Recording = 14
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace MediaBrowser.Model.System
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides the MAC address and port for wake-on-LAN functionality.
|
||||
/// </summary>
|
||||
public class WakeOnLanInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WakeOnLanInfo" /> class.
|
||||
/// </summary>
|
||||
/// <param name="macAddress">The MAC address.</param>
|
||||
public WakeOnLanInfo(PhysicalAddress macAddress) : this(macAddress.ToString())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WakeOnLanInfo" /> class.
|
||||
/// </summary>
|
||||
/// <param name="macAddress">The MAC address.</param>
|
||||
public WakeOnLanInfo(string macAddress) : this()
|
||||
{
|
||||
MacAddress = macAddress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WakeOnLanInfo" /> class.
|
||||
/// </summary>
|
||||
public WakeOnLanInfo()
|
||||
{
|
||||
Port = 9;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MAC address of the device.
|
||||
/// </summary>
|
||||
/// <value>The MAC address.</value>
|
||||
public string? MacAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the wake-on-LAN port.
|
||||
/// </summary>
|
||||
/// <value>The wake-on-LAN port.</value>
|
||||
public int Port { get; set; }
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Extensions;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Jellyfin.Extensions.StringExtensions;
|
||||
|
||||
namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
@ -400,6 +401,24 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
}
|
||||
}
|
||||
|
||||
if (options.ReplaceAllMetadata || !audio.TryGetProviderId(MetadataProvider.MusicBrainzRecording, out _))
|
||||
{
|
||||
if ((track.AdditionalFields.TryGetValue("MUSICBRAINZ_TRACKID", out var recordingMbId)
|
||||
|| track.AdditionalFields.TryGetValue("MusicBrainz Track Id", out recordingMbId))
|
||||
&& !string.IsNullOrEmpty(recordingMbId))
|
||||
{
|
||||
audio.TrySetProviderId(MetadataProvider.MusicBrainzRecording, recordingMbId);
|
||||
}
|
||||
else if (track.AdditionalFields.TryGetValue("UFID", out var ufIdValue) && !string.IsNullOrEmpty(ufIdValue))
|
||||
{
|
||||
// If tagged with MB Picard, the format is 'http://musicbrainz.org\0<recording MBID>'
|
||||
if (ufIdValue.Contains("musicbrainz.org", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
audio.TrySetProviderId(MetadataProvider.MusicBrainzRecording, ufIdValue.AsSpan().RightPart('\0').ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save extracted lyrics if they exist,
|
||||
// and if the audio doesn't yet have lyrics.
|
||||
var lyrics = track.Lyrics.SynchronizedLyrics.Count > 0 ? track.Lyrics.FormatSynchToLRC() : track.Lyrics.UnsynchronizedLyrics;
|
||||
|
@ -0,0 +1,27 @@
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
|
||||
namespace MediaBrowser.Providers.Plugins.MusicBrainz;
|
||||
|
||||
/// <summary>
|
||||
/// MusicBrainz recording id.
|
||||
/// </summary>
|
||||
public class MusicBrainzRecordingId : IExternalId
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string ProviderName => "MusicBrainz";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => MetadataProvider.MusicBrainzRecording.ToString();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ExternalIdMediaType? Type => ExternalIdMediaType.Recording;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string UrlFormatString => Plugin.Instance!.Configuration.Server + "/recording/{0}";
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Supports(IHasProviderIds item) => item is Audio;
|
||||
}
|
@ -55,13 +55,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
|
||||
if (info.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out string? seriesImdbId)
|
||||
&& !string.IsNullOrEmpty(seriesImdbId)
|
||||
&& info.IndexNumber.HasValue
|
||||
&& info.ParentIndexNumber.HasValue)
|
||||
&& info.IndexNumber.HasValue)
|
||||
{
|
||||
result.HasMetadata = await _omdbProvider.FetchEpisodeData(
|
||||
result,
|
||||
info.IndexNumber.Value,
|
||||
info.ParentIndexNumber.Value,
|
||||
info.ParentIndexNumber ?? 1,
|
||||
info.GetProviderId(MetadataProvider.Imdb),
|
||||
seriesImdbId,
|
||||
info.MetadataLanguage,
|
||||
|
@ -63,10 +63,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
return Enumerable.Empty<RemoteImageInfo>();
|
||||
}
|
||||
|
||||
var seasonNumber = episode.ParentIndexNumber;
|
||||
var seasonNumber = episode.ParentIndexNumber ?? 1;
|
||||
var episodeNumber = episode.IndexNumber;
|
||||
|
||||
if (!seasonNumber.HasValue || !episodeNumber.HasValue)
|
||||
if (!episodeNumber.HasValue)
|
||||
{
|
||||
return Enumerable.Empty<RemoteImageInfo>();
|
||||
}
|
||||
@ -75,7 +75,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
|
||||
// TODO use image languages if All Languages isn't toggled, but there's currently no way to get that value in here
|
||||
var episodeResult = await _tmdbClientManager
|
||||
.GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, series.DisplayOrder, null, null, cancellationToken)
|
||||
.GetEpisodeAsync(seriesTmdbId, seasonNumber, episodeNumber.Value, series.DisplayOrder, null, null, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var stills = episodeResult?.Images?.Stills;
|
||||
|
@ -47,7 +47,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
// The search query must either provide an episode number or date
|
||||
if (!searchInfo.IndexNumber.HasValue || !searchInfo.ParentIndexNumber.HasValue)
|
||||
if (!searchInfo.IndexNumber.HasValue)
|
||||
{
|
||||
return Enumerable.Empty<RemoteSearchResult>();
|
||||
}
|
||||
@ -96,10 +96,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
return metadataResult;
|
||||
}
|
||||
|
||||
var seasonNumber = info.ParentIndexNumber;
|
||||
var seasonNumber = info.ParentIndexNumber ?? 1;
|
||||
var episodeNumber = info.IndexNumber;
|
||||
|
||||
if (!seasonNumber.HasValue || !episodeNumber.HasValue)
|
||||
if (!episodeNumber.HasValue)
|
||||
{
|
||||
return metadataResult;
|
||||
}
|
||||
@ -112,7 +112,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
List<TvEpisode>? result = null;
|
||||
for (int? episode = startindex; episode <= endindex; episode++)
|
||||
{
|
||||
var episodeInfo = await _tmdbClientManager.GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episode.Value, info.SeriesDisplayOrder, info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken).ConfigureAwait(false);
|
||||
var episodeInfo = await _tmdbClientManager.GetEpisodeAsync(seriesTmdbId, seasonNumber, episode.Value, info.SeriesDisplayOrder, info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken).ConfigureAwait(false);
|
||||
if (episodeInfo is not null)
|
||||
{
|
||||
(result ??= new List<TvEpisode>()).Add(episodeInfo);
|
||||
@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
else
|
||||
{
|
||||
episodeResult = await _tmdbClientManager
|
||||
.GetEpisodeAsync(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, info.SeriesDisplayOrder, info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken)
|
||||
.GetEpisodeAsync(seriesTmdbId, seasonNumber, episodeNumber.Value, info.SeriesDisplayOrder, info.MetadataLanguage, TmdbUtils.GetImageLanguagesParam(info.MetadataLanguage), cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@ using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Entities.Security;
|
||||
using Jellyfin.Data.Interfaces;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Server.Implementations;
|
||||
|
@ -49,11 +49,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
/// </summary>
|
||||
private bool _eventfire;
|
||||
|
||||
/// <summary>
|
||||
/// List of all interface MAC addresses.
|
||||
/// </summary>
|
||||
private IReadOnlyList<PhysicalAddress> _macAddresses;
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary containing interface addresses and their subnets.
|
||||
/// </summary>
|
||||
@ -91,7 +86,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
_startupConfig = startupConfig;
|
||||
_initLock = new();
|
||||
_interfaces = new List<IPData>();
|
||||
_macAddresses = new List<PhysicalAddress>();
|
||||
_publishedServerUrls = new List<PublishedServerUriOverride>();
|
||||
_networkEventLock = new();
|
||||
_remoteAddressFilter = new List<IPNetwork>();
|
||||
@ -215,7 +209,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// Generate a list of all the interface ip addresses and submasks where that are in the active/unknown state.
|
||||
/// Generate a list of all active mac addresses that aren't loopback addresses.
|
||||
/// </summary>
|
||||
private void InitializeInterfaces()
|
||||
{
|
||||
@ -224,7 +217,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
_logger.LogDebug("Refreshing interfaces.");
|
||||
|
||||
var interfaces = new List<IPData>();
|
||||
var macAddresses = new List<PhysicalAddress>();
|
||||
|
||||
try
|
||||
{
|
||||
@ -236,13 +228,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
try
|
||||
{
|
||||
var ipProperties = adapter.GetIPProperties();
|
||||
var mac = adapter.GetPhysicalAddress();
|
||||
|
||||
// Populate MAC list
|
||||
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && !PhysicalAddress.None.Equals(mac))
|
||||
{
|
||||
macAddresses.Add(mac);
|
||||
}
|
||||
|
||||
// Populate interface list
|
||||
foreach (var info in ipProperties.UnicastAddresses)
|
||||
@ -302,7 +287,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
_logger.LogDebug("Discovered {NumberOfInterfaces} interfaces.", interfaces.Count);
|
||||
_logger.LogDebug("Interfaces addresses: {Addresses}", interfaces.OrderByDescending(s => s.AddressFamily == AddressFamily.InterNetwork).Select(s => s.Address.ToString()));
|
||||
|
||||
_macAddresses = macAddresses;
|
||||
_interfaces = interfaces;
|
||||
}
|
||||
}
|
||||
@ -711,13 +695,6 @@ public class NetworkManager : INetworkManager, IDisposable
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<PhysicalAddress> GetMacAddresses()
|
||||
{
|
||||
// Populated in construction - so always has values.
|
||||
return _macAddresses;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyList<IPData> GetLoopbacks()
|
||||
{
|
||||
|
@ -23,6 +23,10 @@ namespace Jellyfin.Server.Implementations.Tests.Users
|
||||
[InlineData(" ")]
|
||||
[InlineData("")]
|
||||
[InlineData("special characters like & $ ? are not allowed")]
|
||||
[InlineData("thishasaspaceontheend ")]
|
||||
[InlineData(" thishasaspaceatthestart")]
|
||||
[InlineData(" thishasaspaceatbothends ")]
|
||||
[InlineData(" this has a space at both ends and inbetween ")]
|
||||
public void ThrowIfInvalidUsername_WhenInvalidUsername_ThrowsArgumentException(string username)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => UserManager.ThrowIfInvalidUsername(username));
|
||||
|
Loading…
x
Reference in New Issue
Block a user