aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs2
-rw-r--r--src/Jellyfin.Drawing/ImageProcessor.cs26
-rw-r--r--src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs2
-rw-r--r--src/Jellyfin.LiveTv/Guide/GuideManager.cs2
-rw-r--r--src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs2
-rw-r--r--src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs2
-rw-r--r--src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MapDto.cs2
-rw-r--r--src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs2
-rw-r--r--src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs2
-rw-r--r--src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs6
-rw-r--r--src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs4
-rw-r--r--src/Jellyfin.Networking/Jellyfin.Networking.csproj3
-rw-r--r--src/Jellyfin.Networking/Manager/NetworkManager.cs2
-rw-r--r--src/Jellyfin.Networking/PortForwardingHost.cs192
14 files changed, 38 insertions, 211 deletions
diff --git a/src/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs b/src/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs
index 7af77758b..03733d4f8 100644
--- a/src/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs
+++ b/src/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs
@@ -12,7 +12,7 @@ public class SplashscreenBuilder
{
private const int FinalWidth = 1920;
private const int FinalHeight = 1080;
- // generated collage resolution should be higher than the final resolution
+ // generated collage resolution should be greater than the final resolution
private const int WallWidth = FinalWidth * 3;
private const int WallHeight = FinalHeight * 2;
private const int Rows = 6;
diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs
index 5d4732234..0bd3b8920 100644
--- a/src/Jellyfin.Drawing/ImageProcessor.cs
+++ b/src/Jellyfin.Drawing/ImageProcessor.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Mime;
+using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -15,6 +16,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
@@ -404,8 +406,27 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
}
/// <inheritdoc />
+ public string GetImageCacheTag(string baseItemPath, DateTime imageDateModified)
+ => (baseItemPath + imageDateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+
+ /// <inheritdoc />
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
- => (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ => GetImageCacheTag(item.Path, image.DateModified);
+
+ /// <inheritdoc />
+ public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image)
+ => GetImageCacheTag(item.Path, image.DateModified);
+
+ /// <inheritdoc />
+ public string? GetImageCacheTag(BaseItemDto item, ChapterInfo chapter)
+ {
+ if (chapter.ImagePath is null)
+ {
+ return null;
+ }
+
+ return GetImageCacheTag(item.Path, chapter.ImageDateModified);
+ }
/// <inheritdoc />
public string? GetImageCacheTag(BaseItem item, ChapterInfo chapter)
@@ -431,8 +452,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
return null;
}
- return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5()
- .ToString("N", CultureInfo.InvariantCulture);
+ return GetImageCacheTag(user.ProfileImage.Path, user.ProfileImage.LastModified);
}
private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
index c53ef275b..7472f9c66 100644
--- a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
+++ b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs
@@ -52,7 +52,7 @@ namespace Jellyfin.Extensions.Json.Converters
}
catch (FormatException)
{
- // Ignore unconvertable inputs
+ // Ignore unconvertible inputs
}
}
diff --git a/src/Jellyfin.LiveTv/Guide/GuideManager.cs b/src/Jellyfin.LiveTv/Guide/GuideManager.cs
index f657422a0..ff31b7123 100644
--- a/src/Jellyfin.LiveTv/Guide/GuideManager.cs
+++ b/src/Jellyfin.LiveTv/Guide/GuideManager.cs
@@ -265,7 +265,7 @@ public class GuideManager : IGuideManager
if (newPrograms.Count > 0)
{
- _libraryManager.CreateItems(newPrograms, null, cancellationToken);
+ _libraryManager.CreateOrUpdateItems(newPrograms, null, cancellationToken);
await PrecacheImages(newPrograms, maxCacheDate).ConfigureAwait(false);
}
diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs
index c7a57859e..790f60cf0 100644
--- a/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs
+++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirect.cs
@@ -138,7 +138,7 @@ namespace Jellyfin.LiveTv.Listings
var programsInfo = new List<ProgramInfo>();
foreach (ProgramDto schedule in dailySchedules.SelectMany(d => d.Programs))
{
- // _logger.LogDebug("Proccesing Schedule for statio ID " + stationID +
+ // _logger.LogDebug("Processing Schedule for station ID " + stationID +
// " which corresponds to channel " + channelNumber + " and program id " +
// schedule.ProgramId + " which says it has images? " +
// programDict[schedule.ProgramId].hasImageArtwork);
diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs
index 856b7a89b..79bcbe649 100644
--- a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs
+++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs
@@ -8,7 +8,7 @@ namespace Jellyfin.LiveTv.Listings.SchedulesDirectDtos
public class LineupDto
{
/// <summary>
- /// Gets or sets the linup.
+ /// Gets or sets the lineup.
/// </summary>
[JsonPropertyName("lineup")]
public string? Lineup { get; set; }
diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MapDto.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MapDto.cs
index ea583a1ce..89c4ee5a8 100644
--- a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MapDto.cs
+++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MapDto.cs
@@ -23,7 +23,7 @@ namespace Jellyfin.LiveTv.Listings.SchedulesDirectDtos
/// Gets or sets the provider callsign.
/// </summary>
[JsonPropertyName("providerCallsign")]
- public string? ProvderCallsign { get; set; }
+ public string? ProviderCallsign { get; set; }
/// <summary>
/// Gets or sets the logical channel number.
diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs
index cafc8e273..7998a7a92 100644
--- a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs
+++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs
@@ -8,7 +8,7 @@ namespace Jellyfin.LiveTv.Listings.SchedulesDirectDtos
public class MetadataDto
{
/// <summary>
- /// Gets or sets the linup.
+ /// Gets or sets the lineup.
/// </summary>
[JsonPropertyName("lineup")]
public string? Lineup { get; set; }
diff --git a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs
index 8c3906f86..7bfc4bc8b 100644
--- a/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs
+++ b/src/Jellyfin.LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs
@@ -64,7 +64,7 @@ namespace Jellyfin.LiveTv.Listings.SchedulesDirectDtos
public IReadOnlyList<MetadataProgramsDto> Metadata { get; set; } = Array.Empty<MetadataProgramsDto>();
/// <summary>
- /// Gets or sets the list of content raitings.
+ /// Gets or sets the list of content ratings.
/// </summary>
[JsonPropertyName("contentRating")]
public IReadOnlyList<ContentRatingDto> ContentRating { get; set; } = Array.Empty<ContentRatingDto>();
diff --git a/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs b/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs
index 7dc30f727..7938b7a6e 100644
--- a/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/src/Jellyfin.LiveTv/Listings/XmlTvListingsProvider.cs
@@ -84,10 +84,11 @@ namespace Jellyfin.LiveTv.Listings
_logger.LogInformation("Downloading xmltv listings from {Path}", info.Path);
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(info.Path, cancellationToken).ConfigureAwait(false);
+ var redirectedUrl = response.RequestMessage?.RequestUri?.ToString() ?? info.Path;
var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
await using (stream.ConfigureAwait(false))
{
- return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false);
+ return await UnzipIfNeededAndCopy(redirectedUrl, stream, cacheFile, cancellationToken).ConfigureAwait(false);
}
}
else
@@ -112,7 +113,8 @@ namespace Jellyfin.LiveTv.Listings
await using (fileStream.ConfigureAwait(false))
{
- if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase))
+ if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase) ||
+ Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gzip", StringComparison.OrdinalIgnoreCase))
{
try
{
diff --git a/src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs b/src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs
index c8d678e2f..e3afe1513 100644
--- a/src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs
+++ b/src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs
@@ -93,7 +93,7 @@ namespace Jellyfin.LiveTv.TunerHosts
}
else if (!string.IsNullOrWhiteSpace(extInf) && !trimmedLine.StartsWith('#'))
{
- var channel = GetChannelnfo(extInf, tunerHostId, trimmedLine);
+ var channel = GetChannelInfo(extInf, tunerHostId, trimmedLine);
channel.Id = channelIdPrefix + trimmedLine.GetMD5().ToString("N", CultureInfo.InvariantCulture);
channel.Path = trimmedLine;
@@ -106,7 +106,7 @@ namespace Jellyfin.LiveTv.TunerHosts
return channels;
}
- private ChannelInfo GetChannelnfo(string extInf, string tunerHostId, string mediaUrl)
+ private ChannelInfo GetChannelInfo(string extInf, string tunerHostId, string mediaUrl)
{
var channel = new ChannelInfo()
{
diff --git a/src/Jellyfin.Networking/Jellyfin.Networking.csproj b/src/Jellyfin.Networking/Jellyfin.Networking.csproj
index 472cdb7ef..1a146549d 100644
--- a/src/Jellyfin.Networking/Jellyfin.Networking.csproj
+++ b/src/Jellyfin.Networking/Jellyfin.Networking.csproj
@@ -14,7 +14,4 @@
<ProjectReference Include="..\..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
</ItemGroup>
- <ItemGroup>
- <PackageReference Include="Mono.Nat" />
- </ItemGroup>
</Project>
diff --git a/src/Jellyfin.Networking/Manager/NetworkManager.cs b/src/Jellyfin.Networking/Manager/NetworkManager.cs
index b1fc5d406..3f71770b5 100644
--- a/src/Jellyfin.Networking/Manager/NetworkManager.cs
+++ b/src/Jellyfin.Networking/Manager/NetworkManager.cs
@@ -973,7 +973,7 @@ public class NetworkManager : INetworkManager, IDisposable
bindPreference = string.Empty;
int? port = null;
- // Only consider subnets including the source IP, prefering specific overrides
+ // Only consider subnets including the source IP, preferring specific overrides
List<PublishedServerUriOverride> validPublishedServerUrls;
if (!isInExternalSubnet)
{
diff --git a/src/Jellyfin.Networking/PortForwardingHost.cs b/src/Jellyfin.Networking/PortForwardingHost.cs
deleted file mode 100644
index d01343624..000000000
--- a/src/Jellyfin.Networking/PortForwardingHost.cs
+++ /dev/null
@@ -1,192 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Net;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Mono.Nat;
-
-namespace Jellyfin.Networking;
-
-/// <summary>
-/// <see cref="IHostedService"/> responsible for UPnP port forwarding.
-/// </summary>
-public sealed class PortForwardingHost : IHostedService, IDisposable
-{
- private readonly IServerApplicationHost _appHost;
- private readonly ILogger<PortForwardingHost> _logger;
- private readonly IServerConfigurationManager _config;
- private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new();
-
- private Timer? _timer;
- private string? _configIdentifier;
- private bool _disposed;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="PortForwardingHost"/> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <param name="appHost">The application host.</param>
- /// <param name="config">The configuration manager.</param>
- public PortForwardingHost(
- ILogger<PortForwardingHost> logger,
- IServerApplicationHost appHost,
- IServerConfigurationManager config)
- {
- _logger = logger;
- _appHost = appHost;
- _config = config;
- }
-
- private string GetConfigIdentifier()
- {
- const char Separator = '|';
- var config = _config.GetNetworkConfiguration();
-
- return new StringBuilder(32)
- .Append(config.EnableUPnP).Append(Separator)
- .Append(config.PublicHttpPort).Append(Separator)
- .Append(config.PublicHttpsPort).Append(Separator)
- .Append(_appHost.HttpPort).Append(Separator)
- .Append(_appHost.HttpsPort).Append(Separator)
- .Append(_appHost.ListenWithHttps).Append(Separator)
- .Append(config.EnableRemoteAccess).Append(Separator)
- .ToString();
- }
-
- private void OnConfigurationUpdated(object? sender, EventArgs e)
- {
- var oldConfigIdentifier = _configIdentifier;
- _configIdentifier = GetConfigIdentifier();
-
- if (!string.Equals(_configIdentifier, oldConfigIdentifier, StringComparison.OrdinalIgnoreCase))
- {
- Stop();
- Start();
- }
- }
-
- /// <inheritdoc />
- public Task StartAsync(CancellationToken cancellationToken)
- {
- Start();
-
- _config.ConfigurationUpdated += OnConfigurationUpdated;
-
- return Task.CompletedTask;
- }
-
- /// <inheritdoc />
- public Task StopAsync(CancellationToken cancellationToken)
- {
- Stop();
-
- return Task.CompletedTask;
- }
-
- private void Start()
- {
- var config = _config.GetNetworkConfiguration();
- if (!config.EnableUPnP || !config.EnableRemoteAccess)
- {
- return;
- }
-
- _logger.LogInformation("Starting NAT discovery");
-
- NatUtility.DeviceFound += OnNatUtilityDeviceFound;
- NatUtility.StartDiscovery();
-
- _timer?.Dispose();
- _timer = new Timer(_ => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
- }
-
- private void Stop()
- {
- _logger.LogInformation("Stopping NAT discovery");
-
- NatUtility.StopDiscovery();
- NatUtility.DeviceFound -= OnNatUtilityDeviceFound;
-
- _timer?.Dispose();
- _timer = null;
- }
-
- private async void OnNatUtilityDeviceFound(object? sender, DeviceEventArgs e)
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- try
- {
- // On some systems the device discovered event seems to fire repeatedly
- // This check will help ensure we're not trying to port map the same device over and over
- if (!_createdRules.TryAdd(e.Device.DeviceEndpoint, 0))
- {
- return;
- }
-
- await Task.WhenAll(CreatePortMaps(e.Device)).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error creating port forwarding rules");
- }
- }
-
- private IEnumerable<Task> CreatePortMaps(INatDevice device)
- {
- var config = _config.GetNetworkConfiguration();
- yield return CreatePortMap(device, _appHost.HttpPort, config.PublicHttpPort);
-
- if (_appHost.ListenWithHttps)
- {
- yield return CreatePortMap(device, _appHost.HttpsPort, config.PublicHttpsPort);
- }
- }
-
- private async Task CreatePortMap(INatDevice device, int privatePort, int publicPort)
- {
- _logger.LogDebug(
- "Creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}",
- privatePort,
- publicPort,
- device.DeviceEndpoint);
-
- try
- {
- var mapping = new Mapping(Protocol.Tcp, privatePort, publicPort, 0, _appHost.Name);
- await device.CreatePortMapAsync(mapping).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.LogError(
- ex,
- "Error creating port map on local port {LocalPort} to public port {PublicPort} with device {DeviceEndpoint}.",
- privatePort,
- publicPort,
- device.DeviceEndpoint);
- }
- }
-
- /// <inheritdoc />
- public void Dispose()
- {
- if (_disposed)
- {
- return;
- }
-
- _config.ConfigurationUpdated -= OnConfigurationUpdated;
-
- _timer?.Dispose();
- _timer = null;
-
- _disposed = true;
- }
-}