Merge branch 'jellyfin:master' into feature/EFUserData

pull/12798/head
JPVenson 4 months ago committed by GitHub
commit fe1aab034e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,28 +0,0 @@
{
"name": "Development Jellyfin Server - FFmpeg",
"image":"mcr.microsoft.com/devcontainers/dotnet:9.0-jammy",
// restores nuget packages, installs the dotnet workloads and installs the dev https certificate
"postStartCommand": "dotnet restore; dotnet workload update; dotnet dev-certs https --trust; sudo bash \"./.devcontainer/Dev - Server Ffmpeg/install-ffmpeg.sh\"",
// reads the extensions list and installs them
"postAttachCommand": "cat .vscode/extensions.json | jq -r .recommendations[] | xargs -n 1 code --install-extension",
"features": {
"ghcr.io/devcontainers/features/dotnet:2": {
"version": "none",
"dotnetRuntimeVersions": "9.0",
"aspNetCoreRuntimeVersions": "9.0"
},
"ghcr.io/devcontainers-contrib/features/apt-packages:1": {
"preserve_apt_list": false,
"packages": ["libfontconfig1"]
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"dockerDashComposeVersion": "v2"
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/eitsupi/devcontainer-features/jq-likes:2": {}
},
"hostRequirements": {
"memory": "8gb",
"cpus": 4
}
}

@ -1,8 +1,8 @@
{
"name": "Development Jellyfin Server",
"image":"mcr.microsoft.com/devcontainers/dotnet:9.0-jammy",
"image":"mcr.microsoft.com/devcontainers/dotnet:9.0-bookworm",
// restores nuget packages, installs the dotnet workloads and installs the dev https certificate
"postStartCommand": "dotnet restore; dotnet workload update; dotnet dev-certs https --trust",
"postStartCommand": "sudo dotnet restore; sudo dotnet workload update; sudo dotnet dev-certs https --trust; sudo bash \"./.devcontainer/install-ffmpeg.sh\"",
// reads the extensions list and installs them
"postAttachCommand": "cat .vscode/extensions.json | jq -r .recommendations[] | xargs -n 1 code --install-extension",
"features": {

@ -29,4 +29,4 @@ Signed-By: /etc/apt/keyrings/jellyfin.gpg
EOF
sudo apt update -y
sudo apt install jellyfin-ffmpeg6 -y
sudo apt install jellyfin-ffmpeg7 -y

@ -27,11 +27,11 @@ jobs:
dotnet-version: '9.0.x'
- name: Initialize CodeQL
uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
with:
languages: ${{ matrix.language }}
queries: +security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # v3.27.6

@ -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@25ce8cbbcb08177468c7ff7ec5cbfa236f9341e1 # v1.1.0
uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
with:
host: "${{ secrets.REPO_HOST }}"
username: "${{ secrets.REPO_USER }}"
@ -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@25ce8cbbcb08177468c7ff7ec5cbfa236f9341e1 # v1.1.0
uses: appleboy/ssh-action@7eaf76671a0d7eec5d98ee897acda4f968735a17 # v1.2.0
with:
host: "${{ secrets.REPO_HOST }}"
username: "${{ secrets.REPO_USER }}"

@ -1,12 +1,13 @@
{
"recommendations": [
"recommendations": [
"ms-dotnettools.csharp",
"editorconfig.editorconfig",
"github.vscode-github-actions",
"ms-dotnettools.vscode-dotnet-runtime",
"ms-dotnettools.csdevkit"
],
"unwantedRecommendations": [
"ms-dotnettools.csdevkit",
"alexcvzz.vscode-sqlite"
],
"unwantedRecommendations": [
]
]
}

@ -192,6 +192,7 @@
- [jaina heartles](https://github.com/heartles)
- [oxixes](https://github.com/oxixes)
- [elfalem](https://github.com/elfalem)
- [Kenneth Cochran](https://github.com/kennethcochran)
- [benedikt257](https://github.com/benedikt257)
- [revam](https://github.com/revam)

@ -4,7 +4,7 @@
</PropertyGroup>
<!-- Run "dotnet list package (dash,dash)outdated" to see the latest versions of each package.-->
<ItemGroup Label="Package Dependencies">
<PackageVersion Include="AsyncKeyedLock" Version="7.1.3" />
<PackageVersion Include="AsyncKeyedLock" Version="7.1.4" />
<PackageVersion Include="AutoFixture.AutoMoq" Version="4.18.1" />
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageVersion Include="AutoFixture" Version="4.18.1" />
@ -47,8 +47,8 @@
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="MimeTypes" Version="2.4.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageVersion Include="MimeTypes" Version="2.5.2" />
<PackageVersion Include="Mono.Nat" Version="3.0.4" />
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="NEbml" Version="0.11.0" />
@ -71,7 +71,7 @@
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageVersion Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="Svg.Skia" Version="2.0.0.2" />
<PackageVersion Include="Svg.Skia" Version="2.0.0.4" />
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.5.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageVersion Include="System.Globalization" Version="4.3.0" />
@ -80,12 +80,12 @@
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
<PackageVersion Include="System.Threading.Tasks.Dataflow" Version="9.0.0" />
<PackageVersion Include="TagLibSharp" Version="2.3.0" />
<PackageVersion Include="z440.atl.core" Version="6.8.0" />
<PackageVersion Include="z440.atl.core" Version="6.9.0" />
<PackageVersion Include="TMDbLib" Version="2.2.0" />
<PackageVersion Include="UTF.Unknown" Version="2.5.1" />
<PackageVersion Include="Xunit.Priority" Version="1.1.6" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.4.13" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
<PackageVersion Include="xunit" Version="2.9.2" />
</ItemGroup>
</Project>

@ -131,5 +131,6 @@
"TaskRefreshTrickplayImages": "Генерирај слики за прегледување (Trickplay)",
"TaskAudioNormalization": "Нормализација на звукот",
"TaskRefreshTrickplayImagesDescription": "Креира трикплеј прегледи за видеа во овозможените библиотеки.",
"TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат."
"TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат.",
"TaskExtractMediaSegments": "Скенирање на сегменти на содржина"
}

@ -77,7 +77,7 @@
"HeaderAlbumArtists": "Artiști album",
"Genres": "Genuri",
"Folders": "Dosare",
"Favorites": "Favorite",
"Favorites": "Preferate",
"FailedLoginAttemptWithUserName": "Încercare de conectare eșuată pentru {0}",
"DeviceOnlineWithName": "{0} este conectat",
"DeviceOfflineWithName": "{0} s-a deconectat",

@ -133,5 +133,6 @@
"TaskDownloadMissingLyricsDescription": "下載歌詞",
"TaskCleanCollectionsAndPlaylists": "整理媒體與播放清單",
"TaskAudioNormalization": "音訊同等化",
"TaskAudioNormalizationDescription": "掃描檔案裏的音訊同等化資料。"
"TaskAudioNormalizationDescription": "掃描檔案裏的音訊同等化資料。",
"TaskCleanCollectionsAndPlaylistsDescription": "從資料庫及播放清單中移除已不存在的項目。"
}

@ -5,23 +5,23 @@ TV-Y,0
TV-Y7,7
TV-Y7-FV,7
PG,10
TV-PG,10
TV-PG-D,10
TV-PG-L,10
TV-PG-S,10
TV-PG-V,10
TV-PG-DL,10
TV-PG-DS,10
TV-PG-DV,10
TV-PG-LS,10
TV-PG-LV,10
TV-PG-SV,10
TV-PG-DLS,10
TV-PG-DLV,10
TV-PG-DSV,10
TV-PG-LSV,10
TV-PG-DLSV,10
PG-13,13
TV-PG,13
TV-PG-D,13
TV-PG-L,13
TV-PG-S,13
TV-PG-V,13
TV-PG-DL,13
TV-PG-DS,13
TV-PG-DV,13
TV-PG-LS,13
TV-PG-LV,13
TV-PG-SV,13
TV-PG-DLS,13
TV-PG-DLV,13
TV-PG-DSV,13
TV-PG-LSV,13
TV-PG-DLSV,13
TV-14,14
TV-14-D,14
TV-14-L,14

1 Approved 0
5 TV-Y7 7
6 TV-Y7-FV 7
7 PG 10
8 TV-PG 10
9 TV-PG-D 10
10 TV-PG-L 10
11 TV-PG-S 10
12 TV-PG-V 10
13 TV-PG-DL 10
14 TV-PG-DS 10
15 TV-PG-DV 10
16 TV-PG-LS 10
17 TV-PG-LV 10
18 TV-PG-SV 10
19 TV-PG-DLS 10
20 TV-PG-DLV 10
21 TV-PG-DSV 10
22 TV-PG-LSV 10
23 TV-PG-DLSV 10
24 PG-13 13
TV-PG 13
TV-PG-D 13
TV-PG-L 13
TV-PG-S 13
TV-PG-V 13
TV-PG-DL 13
TV-PG-DS 13
TV-PG-DV 13
TV-PG-LS 13
TV-PG-LV 13
TV-PG-SV 13
TV-PG-DLS 13
TV-PG-DLV 13
TV-PG-DSV 13
TV-PG-LSV 13
TV-PG-DLSV 13
25 TV-14 14
26 TV-14-D 14
27 TV-14-L 14

@ -785,30 +785,27 @@ namespace Emby.Server.Implementations.Plugins
var cleaned = false;
var path = entry.Path;
if (_config.RemoveOldPlugins)
// Attempt a cleanup of old folders.
try
{
// Attempt a cleanup of old folders.
try
{
_logger.LogDebug("Deleting {Path}", path);
Directory.Delete(path, true);
cleaned = true;
}
_logger.LogDebug("Deleting {Path}", path);
Directory.Delete(path, true);
cleaned = true;
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception e)
catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
{
_logger.LogWarning(e, "Unable to delete {Path}", path);
}
{
_logger.LogWarning(e, "Unable to delete {Path}", path);
}
if (cleaned)
{
versions.RemoveAt(x);
}
else
{
ChangePluginState(entry, PluginStatus.Deleted);
}
if (cleaned)
{
versions.RemoveAt(x);
}
else
{
ChangePluginState(entry, PluginStatus.Deleted);
}
}

@ -471,7 +471,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
new()
{
IntervalTicks = TimeSpan.FromDays(1).Ticks,
Type = TaskTriggerInfo.TriggerInterval
Type = TaskTriggerInfoType.IntervalTrigger
}
];
}
@ -616,7 +616,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
MaxRuntimeTicks = info.MaxRuntimeTicks
};
if (info.Type.Equals(nameof(DailyTrigger), StringComparison.OrdinalIgnoreCase))
if (info.Type == TaskTriggerInfoType.DailyTrigger)
{
if (!info.TimeOfDayTicks.HasValue)
{
@ -626,7 +626,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
return new DailyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), options);
}
if (info.Type.Equals(nameof(WeeklyTrigger), StringComparison.OrdinalIgnoreCase))
if (info.Type == TaskTriggerInfoType.WeeklyTrigger)
{
if (!info.TimeOfDayTicks.HasValue)
{
@ -641,7 +641,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
return new WeeklyTrigger(TimeSpan.FromTicks(info.TimeOfDayTicks.Value), info.DayOfWeek.Value, options);
}
if (info.Type.Equals(nameof(IntervalTrigger), StringComparison.OrdinalIgnoreCase))
if (info.Type == TaskTriggerInfoType.IntervalTrigger)
{
if (!info.IntervalTicks.HasValue)
{
@ -651,7 +651,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
return new IntervalTrigger(TimeSpan.FromTicks(info.IntervalTicks.Value), options);
}
if (info.Type.Equals(nameof(StartupTrigger), StringComparison.OrdinalIgnoreCase))
if (info.Type == TaskTriggerInfoType.StartupTrigger)
{
return new StartupTrigger(options);
}

@ -156,7 +156,7 @@ public partial class AudioNormalizationTask : IScheduledTask
[
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromHours(24).Ticks
}
];

@ -85,7 +85,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
[
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerDaily,
Type = TaskTriggerInfoType.DailyTrigger,
TimeOfDayTicks = TimeSpan.FromHours(2).Ticks,
MaxRuntimeTicks = TimeSpan.FromHours(4).Ticks
}

@ -135,6 +135,6 @@ public class CleanupCollectionAndPlaylistPathsTask : IScheduledTask
/// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
return [new TaskTriggerInfo() { Type = TaskTriggerInfo.TriggerStartup }];
return [new TaskTriggerInfo() { Type = TaskTriggerInfoType.StartupTrigger }];
}
}

@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
return
[
// Every so often
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
];
}

@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
{
return
[
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
];
}

@ -69,11 +69,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
[
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerStartup
Type = TaskTriggerInfoType.StartupTrigger
},
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromHours(24).Ticks
}
];

@ -111,7 +111,7 @@ public class MediaSegmentExtractionTask : IScheduledTask
{
yield return new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromHours(12).Ticks
};
}

@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
return
[
// Every so often
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
];
}

@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
{
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromDays(7).Ticks
}
};

@ -60,10 +60,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
// At startup
yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerStartup };
yield return new TaskTriggerInfo { Type = TaskTriggerInfoType.StartupTrigger };
// Every so often
yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks };
yield return new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks };
}
/// <inheritdoc />

@ -48,7 +48,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
{
yield return new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromHours(12).Ticks
};
}

@ -1819,16 +1819,13 @@ public class DynamicHlsController : BaseJellyfinApiController
if (isActualOutputVideoCodecHevc || isActualOutputVideoCodecAv1)
{
var requestedRange = state.GetRequestedRangeTypes(state.ActualOutputVideoCodec);
var requestHasDOVI = requestedRange.Contains(VideoRangeType.DOVI.ToString(), StringComparison.OrdinalIgnoreCase);
var requestHasDOVIWithHDR10 = requestedRange.Contains(VideoRangeType.DOVIWithHDR10.ToString(), StringComparison.OrdinalIgnoreCase);
var requestHasDOVIWithHLG = requestedRange.Contains(VideoRangeType.DOVIWithHLG.ToString(), StringComparison.OrdinalIgnoreCase);
var requestHasDOVIWithSDR = requestedRange.Contains(VideoRangeType.DOVIWithSDR.ToString(), StringComparison.OrdinalIgnoreCase);
// Clients reporting Dolby Vision capabilities with fallbacks may only support the fallback layer.
// Only enable Dolby Vision remuxing if the client explicitly declares support for profiles without fallbacks.
var clientSupportsDoVi = requestedRange.Contains(VideoRangeType.DOVI.ToString(), StringComparison.OrdinalIgnoreCase);
var videoIsDoVi = state.VideoStream.VideoRangeType is VideoRangeType.DOVI or VideoRangeType.DOVIWithHDR10 or VideoRangeType.DOVIWithHLG or VideoRangeType.DOVIWithSDR;
if (EncodingHelper.IsCopyCodec(codec)
&& ((state.VideoStream.VideoRangeType == VideoRangeType.DOVI && requestHasDOVI)
|| (state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithHDR10 && requestHasDOVIWithHDR10)
|| (state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithHLG && requestHasDOVIWithHLG)
|| (state.VideoStream.VideoRangeType == VideoRangeType.DOVIWithSDR && requestHasDOVIWithSDR)))
&& (videoIsDoVi && clientSupportsDoVi))
{
if (isActualOutputVideoCodecHevc)
{

@ -962,9 +962,9 @@ public class LiveTvController : BaseJellyfinApiController
}
/// <summary>
/// Get guid info.
/// Get guide info.
/// </summary>
/// <response code="200">Guid info returned.</response>
/// <response code="200">Guide info returned.</response>
/// <returns>An <see cref="OkResult"/> containing the guide info.</returns>
[HttpGet("GuideInfo")]
[Authorize(Policy = Policies.LiveTvAccess)]

@ -61,7 +61,7 @@ public class MediaSegmentManager : IMediaSegmentManager
.Where(e => !libraryOptions.DisabledMediaSegmentProviders.Contains(GetProviderId(e.Name)))
.OrderBy(i =>
{
var index = libraryOptions.MediaSegmentProvideOrder.IndexOf(i.Name);
var index = libraryOptions.MediaSegmentProviderOrder.IndexOf(i.Name);
return index == -1 ? int.MaxValue : index;
})
.ToList();

@ -30,7 +30,7 @@ namespace Jellyfin.Server.Migrations.Routines
}
/// <inheritdoc/>
public Guid Id => Guid.Parse("{67445D54-B895-4B24-9F4C-35CE0690EA07}");
public Guid Id => Guid.Parse("{73DAB92A-178B-48CD-B05B-FE18733ACDC8}");
/// <inheritdoc/>
public string Name => "MigrateRatingLevels";

@ -15,7 +15,7 @@ namespace MediaBrowser.Model.Configuration
TypeOptions = Array.Empty<TypeOptions>();
DisabledSubtitleFetchers = Array.Empty<string>();
DisabledMediaSegmentProviders = Array.Empty<string>();
MediaSegmentProvideOrder = Array.Empty<string>();
MediaSegmentProviderOrder = Array.Empty<string>();
SubtitleFetcherOrder = Array.Empty<string>();
DisabledLocalMetadataReaders = Array.Empty<string>();
DisabledLyricFetchers = Array.Empty<string>();
@ -99,7 +99,7 @@ namespace MediaBrowser.Model.Configuration
public string[] DisabledMediaSegmentProviders { get; set; }
public string[] MediaSegmentProvideOrder { get; set; }
public string[] MediaSegmentProviderOrder { get; set; }
public bool SkipSubtitlesIfEmbeddedSubtitlesPresent { get; set; }

@ -243,11 +243,6 @@ public class ServerConfiguration : BaseApplicationConfiguration
/// </summary>
public int LibraryMetadataRefreshConcurrency { get; set; }
/// <summary>
/// Gets or sets a value indicating whether older plugins should automatically be deleted from the plugin folder.
/// </summary>
public bool RemoveOldPlugins { get; set; }
/// <summary>
/// Gets or sets a value indicating whether clients should be allowed to upload logs.
/// </summary>

@ -125,6 +125,7 @@ namespace MediaBrowser.Model.Net
new("audio/vorbis", ".vorbis"),
new("audio/x-ape", ".ape"),
new("audio/xsp", ".xsp"),
new("audio/x-aac", ".aac"),
new("audio/x-wavpack", ".wv"),
// Type image

@ -8,31 +8,11 @@ namespace MediaBrowser.Model.Tasks
/// </summary>
public class TaskTriggerInfo
{
/// <summary>
/// The daily trigger.
/// </summary>
public const string TriggerDaily = "DailyTrigger";
/// <summary>
/// The weekly trigger.
/// </summary>
public const string TriggerWeekly = "WeeklyTrigger";
/// <summary>
/// The interval trigger.
/// </summary>
public const string TriggerInterval = "IntervalTrigger";
/// <summary>
/// The startup trigger.
/// </summary>
public const string TriggerStartup = "StartupTrigger";
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public string Type { get; set; }
public TaskTriggerInfoType Type { get; set; }
/// <summary>
/// Gets or sets the time of day.

@ -0,0 +1,28 @@
namespace MediaBrowser.Model.Tasks
{
/// <summary>
/// Enum TaskTriggerInfoType.
/// </summary>
public enum TaskTriggerInfoType
{
/// <summary>
/// The daily trigger.
/// </summary>
DailyTrigger,
/// <summary>
/// The weekly trigger.
/// </summary>
WeeklyTrigger,
/// <summary>
/// The interval trigger.
/// </summary>
IntervalTrigger,
/// <summary>
/// The startup trigger.
/// </summary>
StartupTrigger
}
}

@ -162,7 +162,7 @@ public class LyricScheduledTask : IScheduledTask
[
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromHours(24).Ticks
}
];

@ -217,7 +217,7 @@ namespace MediaBrowser.Providers.MediaInfo
return new[]
{
// Every so often
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }
new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks }
};
}
}

@ -63,7 +63,7 @@ public class TrickplayImagesTask : IScheduledTask
{
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerDaily,
Type = TaskTriggerInfoType.DailyTrigger,
TimeOfDayTicks = TimeSpan.FromHours(3).Ticks
}
};

@ -79,7 +79,7 @@ namespace Jellyfin.LiveTv.Channels
// Every so often
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks
Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks
}
};
}

@ -66,7 +66,7 @@ public class RefreshGuideScheduledTask : IScheduledTask, IConfigurableScheduledT
{
new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
Type = TaskTriggerInfoType.IntervalTrigger,
IntervalTicks = TimeSpan.FromHours(24).Ticks
}
};

@ -0,0 +1,50 @@
using System;
using Jellyfin.LiveTv.Configuration;
using Jellyfin.LiveTv.Listings;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
namespace Jellyfin.LiveTv.Tests.Listings;
public class ListingsManagerTests
{
private readonly IConfigurationManager _config;
private readonly IListingsProvider[] _listingsProviders;
private readonly ILogger<ListingsManager> _logger;
private readonly ITaskManager _taskManager;
private readonly ITunerHostManager _tunerHostManager;
public ListingsManagerTests()
{
_logger = Mock.Of<ILogger<ListingsManager>>();
_config = Mock.Of<IConfigurationManager>();
_taskManager = Mock.Of<ITaskManager>();
_tunerHostManager = Mock.Of<ITunerHostManager>();
_listingsProviders = new[] { Mock.Of<IListingsProvider>() };
}
[Fact]
public void DeleteListingsProvider_DeletesProvider()
{
// Arrange
var id = "MockId";
var manager = new ListingsManager(_logger, _config, _taskManager, _tunerHostManager, _listingsProviders);
Mock.Get(_config)
.Setup(x => x.GetConfiguration(It.IsAny<string>()))
.Returns(new LiveTvOptions { ListingProviders = [new ListingsProviderInfo { Id = id }] });
// Act
manager.DeleteListingsProvider(id);
// Assert
Assert.DoesNotContain(
_config.GetLiveTvConfiguration().ListingProviders,
p => p.Id.Equals(id, StringComparison.Ordinal));
}
}
Loading…
Cancel
Save