Merge remote-tracking branch 'upstream/master' into api-doc-base-url

pull/4035/head
crobibero 4 years ago
commit 9f97c47936

@ -14,7 +14,7 @@ COPY . .
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# because of changes in docker and systemd we need to not build in parallel at the moment
# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="/jellyfin" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none"
FROM debian:buster-slim

@ -21,7 +21,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# Discard objs - may cause failures if exists
RUN find . -type d -name obj | xargs -r rm -r
# Build
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none"
FROM multiarch/qemu-user-static:x86_64-arm as qemu

@ -21,7 +21,7 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# Discard objs - may cause failures if exists
RUN find . -type d -name obj | xargs -r rm -r
# Build
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --configuration Release --output="/jellyfin" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none"
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
FROM arm64v8/debian:buster-slim

@ -1,4 +1,5 @@
using System.Net.Mime;
using MediaBrowser.Common.Json;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api
@ -8,7 +9,10 @@ namespace Jellyfin.Api
/// </summary>
[ApiController]
[Route("[controller]")]
[Produces(MediaTypeNames.Application.Json)]
[Produces(
MediaTypeNames.Application.Json,
JsonDefaults.CamelCaseMediaType,
JsonDefaults.PascalCaseMediaType)]
public class BaseJellyfinApiController : ControllerBase
{
}

@ -1,6 +1,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Mime;
using System.Threading.Tasks;
using Emby.Dlna;
using Emby.Dlna.Main;
@ -17,8 +18,6 @@ namespace Jellyfin.Api.Controllers
[Route("Dlna")]
public class DlnaServerController : BaseJellyfinApiController
{
private const string XMLContentType = "text/xml; charset=UTF-8";
private readonly IDlnaManager _dlnaManager;
private readonly IContentDirectory _contentDirectory;
private readonly IConnectionManager _connectionManager;
@ -44,7 +43,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>An <see cref="OkResult"/> containing the description xml.</returns>
[HttpGet("{serverId}/description")]
[HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")]
[Produces(XMLContentType)]
[Produces(MediaTypeNames.Text.Xml)]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetDescriptionXml([FromRoute] string serverId)
{
@ -63,7 +62,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("{serverId}/ContentDirectory")]
[HttpGet("{serverId}/ContentDirectory/ContentDirectory", Name = "GetContentDirectory_2")]
[HttpGet("{serverId}/ContentDirectory/ContentDirectory.xml", Name = "GetContentDirectory_3")]
[Produces(XMLContentType)]
[Produces(MediaTypeNames.Text.Xml)]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
public ActionResult GetContentDirectory([FromRoute] string serverId)
@ -79,7 +78,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("{serverId}/MediaReceiverRegistrar")]
[HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar", Name = "GetMediaReceiverRegistrar_2")]
[HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar.xml", Name = "GetMediaReceiverRegistrar_3")]
[Produces(XMLContentType)]
[Produces(MediaTypeNames.Text.Xml)]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
public ActionResult GetMediaReceiverRegistrar([FromRoute] string serverId)
@ -95,7 +94,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("{serverId}/ConnectionManager")]
[HttpGet("{serverId}/ConnectionManager/ConnectionManager", Name = "GetConnectionManager_2")]
[HttpGet("{serverId}/ConnectionManager/ConnectionManager.xml", Name = "GetConnectionManager_3")]
[Produces(XMLContentType)]
[Produces(MediaTypeNames.Text.Xml)]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
public ActionResult GetConnectionManager([FromRoute] string serverId)

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Jellyfin.Api;
using Jellyfin.Api.Auth;
using Jellyfin.Api.Auth.DefaultAuthorizationPolicy;
using Jellyfin.Api.Auth.DownloadPolicy;
@ -18,7 +17,6 @@ using Jellyfin.Api.Constants;
using Jellyfin.Api.Controllers;
using Jellyfin.Server.Formatters;
using Jellyfin.Server.Models;
using MediaBrowser.Common;
using MediaBrowser.Common.Json;
using MediaBrowser.Model.Entities;
using Microsoft.AspNetCore.Authentication;
@ -150,6 +148,9 @@ namespace Jellyfin.Server.Extensions
})
.AddMvc(opts =>
{
// Allow requester to change between camelCase and PascalCase
opts.RespectBrowserAcceptHeader = true;
opts.OutputFormatters.Insert(0, new CamelCaseJsonProfileFormatter());
opts.OutputFormatters.Insert(0, new PascalCaseJsonProfileFormatter());

@ -15,7 +15,7 @@ namespace Jellyfin.Server.Formatters
public CamelCaseJsonProfileFormatter() : base(JsonDefaults.GetCamelCaseOptions())
{
SupportedMediaTypes.Clear();
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json;profile=\"CamelCase\""));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(JsonDefaults.CamelCaseMediaType));
}
}
}

@ -1,3 +1,4 @@
using System.Net.Mime;
using MediaBrowser.Common.Json;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Net.Http.Headers;
@ -16,8 +17,8 @@ namespace Jellyfin.Server.Formatters
{
SupportedMediaTypes.Clear();
// Add application/json for default formatter
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json;profile=\"PascalCase\""));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(MediaTypeNames.Application.Json));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse(JsonDefaults.PascalCaseMediaType));
}
}
}

@ -16,8 +16,9 @@ namespace Jellyfin.Server.Formatters
/// </summary>
public XmlOutputFormatter()
{
SupportedMediaTypes.Clear();
SupportedMediaTypes.Add(MediaTypeNames.Text.Xml);
SupportedMediaTypes.Add("text/xml;charset=UTF-8");
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
}

@ -1,36 +0,0 @@
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Server.Implementations;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Jellyfin.Server.HealthChecks
{
/// <summary>
/// Checks connectivity to the database.
/// </summary>
public class JellyfinDbHealthCheck : IHealthCheck
{
private readonly JellyfinDbProvider _dbProvider;
/// <summary>
/// Initializes a new instance of the <see cref="JellyfinDbHealthCheck"/> class.
/// </summary>
/// <param name="dbProvider">The jellyfin db provider.</param>
public JellyfinDbHealthCheck(JellyfinDbProvider dbProvider)
{
_dbProvider = dbProvider;
}
/// <inheritdoc />
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
await using var jellyfinDb = _dbProvider.CreateContext();
if (await jellyfinDb.Database.CanConnectAsync(cancellationToken).ConfigureAwait(false))
{
return HealthCheckResult.Healthy("Database connection successful.");
}
return HealthCheckResult.Unhealthy("Unable to connect to the database.");
}
}
}

@ -44,6 +44,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.7" />
<PackageReference Include="prometheus-net" Version="3.6.0" />
<PackageReference Include="prometheus-net.AspNetCore" Version="3.6.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />

@ -3,7 +3,7 @@ using System.ComponentModel;
using System.Net.Http.Headers;
using Jellyfin.Api.TypeConverters;
using Jellyfin.Server.Extensions;
using Jellyfin.Server.HealthChecks;
using Jellyfin.Server.Implementations;
using Jellyfin.Server.Middleware;
using Jellyfin.Server.Models;
using MediaBrowser.Common.Net;
@ -80,7 +80,7 @@ namespace Jellyfin.Server
.ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler());
services.AddHealthChecks()
.AddCheck<JellyfinDbHealthCheck>("JellyfinDb");
.AddDbContextCheck<JellyfinDb>();
}
/// <summary>

@ -9,6 +9,16 @@ namespace MediaBrowser.Common.Json
/// </summary>
public static class JsonDefaults
{
/// <summary>
/// Pascal case json profile media type.
/// </summary>
public const string PascalCaseMediaType = "application/json; profile=\"PascalCase\"";
/// <summary>
/// Camel case json profile media type.
/// </summary>
public const string CamelCaseMediaType = "application/json; profile=\"CamelCase\"";
/// <summary>
/// Gets the default <see cref="JsonSerializerOptions" /> options.
/// </summary>

@ -60,8 +60,6 @@ namespace MediaBrowser.Controller.Entities
protected BaseItem()
{
ThemeSongIds = Array.Empty<Guid>();
ThemeVideoIds = Array.Empty<Guid>();
Tags = Array.Empty<string>();
Genres = Array.Empty<string>();
Studios = Array.Empty<string>();
@ -100,12 +98,52 @@ namespace MediaBrowser.Controller.Entities
};
[JsonIgnore]
public Guid[] ThemeSongIds { get; set; }
public Guid[] ThemeSongIds
{
get
{
if (_themeSongIds == null)
{
_themeSongIds = GetExtras()
.Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong)
.Select(song => song.Id)
.ToArray();
}
return _themeSongIds;
}
private set
{
_themeSongIds = value;
}
}
[JsonIgnore]
public Guid[] ThemeVideoIds { get; set; }
public Guid[] ThemeVideoIds
{
get
{
if (_themeVideoIds == null)
{
_themeVideoIds = GetExtras()
.Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo)
.Select(song => song.Id)
.ToArray();
}
return _themeVideoIds;
}
private set
{
_themeVideoIds = value;
}
}
[JsonIgnore]
public string PreferredMetadataCountryCode { get; set; }
[JsonIgnore]
public string PreferredMetadataLanguage { get; set; }
@ -635,6 +673,9 @@ namespace MediaBrowser.Controller.Entities
}
private string _sortName;
private Guid[] _themeSongIds;
private Guid[] _themeVideoIds;
/// <summary>
/// Gets the name of the sort.
/// </summary>
@ -1582,7 +1623,8 @@ namespace MediaBrowser.Controller.Entities
await Task.WhenAll(tasks).ConfigureAwait(false);
item.ThemeVideoIds = newThemeVideoIds;
// They are expected to be sorted by SortName
item.ThemeVideoIds = newThemeVideos.OrderBy(i => i.SortName).Select(i => i.Id).ToArray();
return themeVideosChanged;
}
@ -1619,7 +1661,8 @@ namespace MediaBrowser.Controller.Entities
await Task.WhenAll(tasks).ConfigureAwait(false);
item.ThemeSongIds = newThemeSongIds;
// They are expected to be sorted by SortName
item.ThemeSongIds = newThemeSongs.OrderBy(i => i.SortName).Select(i => i.Id).ToArray();
return themeSongsChanged;
}
@ -2910,12 +2953,12 @@ namespace MediaBrowser.Controller.Entities
public IEnumerable<BaseItem> GetThemeSongs()
{
return ThemeVideoIds.Select(LibraryManager.GetItemById).Where(i => i.ExtraType.Equals(Model.Entities.ExtraType.ThemeSong)).OrderBy(i => i.SortName);
return ThemeSongIds.Select(LibraryManager.GetItemById);
}
public IEnumerable<BaseItem> GetThemeVideos()
{
return ThemeVideoIds.Select(LibraryManager.GetItemById).Where(i => i.ExtraType.Equals(Model.Entities.ExtraType.ThemeVideo)).OrderBy(i => i.SortName);
return ThemeVideoIds.Select(LibraryManager.GetItemById);
}
/// <summary>

2
debian/rules vendored

@ -40,7 +40,7 @@ override_dh_clistrip:
override_dh_auto_build:
dotnet publish --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime $(DOTNETRUNTIME) \
"-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none" Jellyfin.Server
"-p:DebugSymbols=false;DebugType=none" Jellyfin.Server
override_dh_auto_clean:
dotnet clean -maxcpucount:1 --configuration $(CONFIG) Jellyfin.Server || true

@ -12,4 +12,4 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# because of changes in docker and systemd we need to not build in parallel at the moment
# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="${ARTIFACT_DIR}" --self-contained --runtime linux-x64 "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="${ARTIFACT_DIR}" --self-contained --runtime linux-x64 "-p:DebugSymbols=false;DebugType=none"

@ -12,4 +12,4 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# because of changes in docker and systemd we need to not build in parallel at the moment
# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="${ARTIFACT_DIR}" --self-contained --runtime linux-arm64 "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="${ARTIFACT_DIR}" --self-contained --runtime linux-arm64 "-p:DebugSymbols=false;DebugType=none"

@ -12,4 +12,4 @@ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
# because of changes in docker and systemd we need to not build in parallel at the moment
# see https://success.docker.com/article/how-to-reserve-resource-temporarily-unavailable-errors-due-to-tasksmax-setting
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="${ARTIFACT_DIR}" --self-contained --runtime linux-arm "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none"
RUN dotnet publish Jellyfin.Server --disable-parallel --configuration Release --output="${ARTIFACT_DIR}" --self-contained --runtime linux-arm "-p:DebugSymbols=false;DebugType=none"

@ -16,7 +16,7 @@ else
fi
# Build archives
dotnet publish Jellyfin.Server --configuration Release --self-contained --runtime linux-x64 --output dist/jellyfin-server_${version}/ "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none;UseAppHost=true"
dotnet publish Jellyfin.Server --configuration Release --self-contained --runtime linux-x64 --output dist/jellyfin-server_${version}/ "-p:DebugSymbols=false;DebugType=none;UseAppHost=true"
tar -czf jellyfin-server_${version}_linux-amd64.tar.gz -C dist jellyfin-server_${version}
rm -rf dist/jellyfin-server_${version}

@ -16,7 +16,7 @@ else
fi
# Build archives
dotnet publish Jellyfin.Server --configuration Release --self-contained --runtime osx-x64 --output dist/jellyfin-server_${version}/ "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none;UseAppHost=true"
dotnet publish Jellyfin.Server --configuration Release --self-contained --runtime osx-x64 --output dist/jellyfin-server_${version}/ "-p:DebugSymbols=false;DebugType=none;UseAppHost=true"
tar -czf jellyfin-server_${version}_macos-amd64.tar.gz -C dist jellyfin-server_${version}
rm -rf dist/jellyfin-server_${version}

@ -16,7 +16,7 @@ else
fi
# Build archives
dotnet publish Jellyfin.Server --configuration Release --output dist/jellyfin-server_${version}/ "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none;UseAppHost=true"
dotnet publish Jellyfin.Server --configuration Release --output dist/jellyfin-server_${version}/ "-p:DebugSymbols=false;DebugType=none;UseAppHost=true"
tar -czf jellyfin-server_${version}_portable.tar.gz -C dist jellyfin-server_${version}
rm -rf dist/jellyfin-server_${version}

@ -23,7 +23,7 @@ fi
output_dir="dist/jellyfin-server_${version}"
# Build binary
dotnet publish Jellyfin.Server --configuration Release --self-contained --runtime win-x64 --output ${output_dir}/ "-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none;UseAppHost=true"
dotnet publish Jellyfin.Server --configuration Release --self-contained --runtime win-x64 --output ${output_dir}/ "-p:DebugSymbols=false;DebugType=none;UseAppHost=true"
# Prepare addins
addin_build_dir="$( mktemp -d )"

@ -54,7 +54,7 @@ The Jellyfin media server backend.
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
dotnet publish --configuration Release --output='%{buildroot}%{_libdir}/jellyfin' --self-contained --runtime %{dotnet_runtime} \
"-p:GenerateDocumentationFile=true;DebugSymbols=false;DebugType=none" Jellyfin.Server
"-p:DebugSymbols=false;DebugType=none" Jellyfin.Server
%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/jellyfin/LICENSE
%{__install} -D -m 0644 %{SOURCE15} %{buildroot}%{_sysconfdir}/systemd/system/jellyfin.service.d/override.conf
%{__install} -D -m 0644 Jellyfin.Server/Resources/Configuration/logging.json %{buildroot}%{_sysconfdir}/jellyfin/logging.json

Loading…
Cancel
Save