mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* sync plex platform and platform version * fix mixed-platform path replacementspull/107/head
15 changed files with 2075 additions and 35 deletions
@ -0,0 +1,147 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using ErsatzTV.Core.Interfaces.Repositories; |
||||||
|
using ErsatzTV.Core.Interfaces.Runtime; |
||||||
|
using ErsatzTV.Core.Plex; |
||||||
|
using FluentAssertions; |
||||||
|
using LanguageExt; |
||||||
|
using Microsoft.Extensions.Logging; |
||||||
|
using Moq; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Tests.Plex |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class PlexPathReplacementServiceTests |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public async Task PlexWindows_To_EtvWindows() |
||||||
|
{ |
||||||
|
var replacements = new List<PlexPathReplacement> |
||||||
|
{ |
||||||
|
new() |
||||||
|
{ |
||||||
|
Id = 1, |
||||||
|
PlexPath = @"C:\Something\Some Shared Folder", |
||||||
|
LocalPath = @"C:\Something Else\Some Shared Folder", |
||||||
|
PlexMediaSource = new PlexMediaSource { Platform = "Windows" } |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var repo = new Mock<IMediaSourceRepository>(); |
||||||
|
repo.Setup(x => x.GetPlexPathReplacementsByLibraryId(It.IsAny<int>())).Returns(replacements.AsTask()); |
||||||
|
|
||||||
|
var runtime = new Mock<IRuntimeInfo>(); |
||||||
|
runtime.Setup(x => x.IsOSPlatform(OSPlatform.Windows)).Returns(true); |
||||||
|
|
||||||
|
var service = new PlexPathReplacementService( |
||||||
|
repo.Object, |
||||||
|
runtime.Object, |
||||||
|
new Mock<ILogger<PlexPathReplacementService>>().Object); |
||||||
|
|
||||||
|
string result = await service.GetReplacementPlexPath( |
||||||
|
0, |
||||||
|
@"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); |
||||||
|
|
||||||
|
result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public async Task PlexWindows_To_EtvLinux() |
||||||
|
{ |
||||||
|
var replacements = new List<PlexPathReplacement> |
||||||
|
{ |
||||||
|
new() |
||||||
|
{ |
||||||
|
Id = 1, |
||||||
|
PlexPath = @"C:\Something\Some Shared Folder", |
||||||
|
LocalPath = @"/mnt/something else/Some Shared Folder", |
||||||
|
PlexMediaSource = new PlexMediaSource { Platform = "Windows" } |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var repo = new Mock<IMediaSourceRepository>(); |
||||||
|
repo.Setup(x => x.GetPlexPathReplacementsByLibraryId(It.IsAny<int>())).Returns(replacements.AsTask()); |
||||||
|
|
||||||
|
var runtime = new Mock<IRuntimeInfo>(); |
||||||
|
runtime.Setup(x => x.IsOSPlatform(OSPlatform.Windows)).Returns(false); |
||||||
|
|
||||||
|
var service = new PlexPathReplacementService( |
||||||
|
repo.Object, |
||||||
|
runtime.Object, |
||||||
|
new Mock<ILogger<PlexPathReplacementService>>().Object); |
||||||
|
|
||||||
|
string result = await service.GetReplacementPlexPath( |
||||||
|
0, |
||||||
|
@"C:\Something\Some Shared Folder\Some Movie\Some Movie.mkv"); |
||||||
|
|
||||||
|
result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public async Task PlexLinux_To_EtvWindows() |
||||||
|
{ |
||||||
|
var replacements = new List<PlexPathReplacement> |
||||||
|
{ |
||||||
|
new() |
||||||
|
{ |
||||||
|
Id = 1, |
||||||
|
PlexPath = @"/mnt/something/Some Shared Folder", |
||||||
|
LocalPath = @"C:\Something Else\Some Shared Folder", |
||||||
|
PlexMediaSource = new PlexMediaSource { Platform = "Linux" } |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var repo = new Mock<IMediaSourceRepository>(); |
||||||
|
repo.Setup(x => x.GetPlexPathReplacementsByLibraryId(It.IsAny<int>())).Returns(replacements.AsTask()); |
||||||
|
|
||||||
|
var runtime = new Mock<IRuntimeInfo>(); |
||||||
|
runtime.Setup(x => x.IsOSPlatform(OSPlatform.Windows)).Returns(true); |
||||||
|
|
||||||
|
var service = new PlexPathReplacementService( |
||||||
|
repo.Object, |
||||||
|
runtime.Object, |
||||||
|
new Mock<ILogger<PlexPathReplacementService>>().Object); |
||||||
|
|
||||||
|
string result = await service.GetReplacementPlexPath( |
||||||
|
0, |
||||||
|
@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); |
||||||
|
|
||||||
|
result.Should().Be(@"C:\Something Else\Some Shared Folder\Some Movie\Some Movie.mkv"); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public async Task PlexLinux_To_EtvLinux() |
||||||
|
{ |
||||||
|
var replacements = new List<PlexPathReplacement> |
||||||
|
{ |
||||||
|
new() |
||||||
|
{ |
||||||
|
Id = 1, |
||||||
|
PlexPath = @"/mnt/something/Some Shared Folder", |
||||||
|
LocalPath = @"/mnt/something else/Some Shared Folder", |
||||||
|
PlexMediaSource = new PlexMediaSource { Platform = "Linux" } |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var repo = new Mock<IMediaSourceRepository>(); |
||||||
|
repo.Setup(x => x.GetPlexPathReplacementsByLibraryId(It.IsAny<int>())).Returns(replacements.AsTask()); |
||||||
|
|
||||||
|
var runtime = new Mock<IRuntimeInfo>(); |
||||||
|
runtime.Setup(x => x.IsOSPlatform(OSPlatform.Windows)).Returns(false); |
||||||
|
|
||||||
|
var service = new PlexPathReplacementService( |
||||||
|
repo.Object, |
||||||
|
runtime.Object, |
||||||
|
new Mock<ILogger<PlexPathReplacementService>>().Object); |
||||||
|
|
||||||
|
string result = await service.GetReplacementPlexPath( |
||||||
|
0, |
||||||
|
@"/mnt/something/Some Shared Folder/Some Movie/Some Movie.mkv"); |
||||||
|
|
||||||
|
result.Should().Be(@"/mnt/something else/Some Shared Folder/Some Movie/Some Movie.mkv"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
using System.Threading.Tasks; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Interfaces.Plex |
||||||
|
{ |
||||||
|
public interface IPlexPathReplacementService |
||||||
|
{ |
||||||
|
Task<string> GetReplacementPlexPath(int libraryPathId, string path); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
using System.Diagnostics.CodeAnalysis; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Interfaces.Runtime |
||||||
|
{ |
||||||
|
public interface IRuntimeInfo |
||||||
|
{ |
||||||
|
[SuppressMessage("ReSharper", "InconsistentNaming")] |
||||||
|
bool IsOSPlatform(OSPlatform osPlatform); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Runtime.InteropServices; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using ErsatzTV.Core.Interfaces.Plex; |
||||||
|
using ErsatzTV.Core.Interfaces.Repositories; |
||||||
|
using ErsatzTV.Core.Interfaces.Runtime; |
||||||
|
using LanguageExt; |
||||||
|
using Microsoft.Extensions.Logging; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Plex |
||||||
|
{ |
||||||
|
public class PlexPathReplacementService : IPlexPathReplacementService |
||||||
|
{ |
||||||
|
private readonly ILogger<PlexPathReplacementService> _logger; |
||||||
|
private readonly IMediaSourceRepository _mediaSourceRepository; |
||||||
|
private readonly IRuntimeInfo _runtimeInfo; |
||||||
|
|
||||||
|
public PlexPathReplacementService( |
||||||
|
IMediaSourceRepository mediaSourceRepository, |
||||||
|
IRuntimeInfo runtimeInfo, |
||||||
|
ILogger<PlexPathReplacementService> logger) |
||||||
|
{ |
||||||
|
_mediaSourceRepository = mediaSourceRepository; |
||||||
|
_runtimeInfo = runtimeInfo; |
||||||
|
_logger = logger; |
||||||
|
} |
||||||
|
|
||||||
|
public async Task<string> GetReplacementPlexPath(int libraryPathId, string path) |
||||||
|
{ |
||||||
|
List<PlexPathReplacement> replacements = |
||||||
|
await _mediaSourceRepository.GetPlexPathReplacementsByLibraryId(libraryPathId); |
||||||
|
Option<PlexPathReplacement> maybeReplacement = replacements |
||||||
|
.SingleOrDefault( |
||||||
|
r => |
||||||
|
{ |
||||||
|
string separatorChar = IsWindows(r.PlexMediaSource) ? @"\" : @"/"; |
||||||
|
return path.StartsWith(r.PlexPath + separatorChar); |
||||||
|
}); |
||||||
|
return maybeReplacement.Match( |
||||||
|
replacement => |
||||||
|
{ |
||||||
|
string finalPath = path.Replace(replacement.PlexPath, replacement.LocalPath); |
||||||
|
if (IsWindows(replacement.PlexMediaSource) && !_runtimeInfo.IsOSPlatform(OSPlatform.Windows)) |
||||||
|
{ |
||||||
|
finalPath = finalPath.Replace(@"\", @"/"); |
||||||
|
} |
||||||
|
else if (!IsWindows(replacement.PlexMediaSource) && _runtimeInfo.IsOSPlatform(OSPlatform.Windows)) |
||||||
|
{ |
||||||
|
finalPath = finalPath.Replace(@"/", @"\"); |
||||||
|
} |
||||||
|
|
||||||
|
_logger.LogInformation( |
||||||
|
"Replacing plex path {PlexPath} with {LocalPath} resulting in {FinalPath}", |
||||||
|
replacement.PlexPath, |
||||||
|
replacement.LocalPath, |
||||||
|
finalPath); |
||||||
|
return finalPath; |
||||||
|
}, |
||||||
|
() => path); |
||||||
|
} |
||||||
|
|
||||||
|
private static bool IsWindows(PlexMediaSource plexMediaSource) => |
||||||
|
plexMediaSource.Platform.ToLowerInvariant() == "windows"; |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,33 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations |
||||||
|
{ |
||||||
|
public partial class Add_PlexMediaSourcePlatform : Migration |
||||||
|
{ |
||||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
migrationBuilder.AddColumn<string>( |
||||||
|
"Platform", |
||||||
|
"PlexMediaSource", |
||||||
|
"TEXT", |
||||||
|
nullable: true); |
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>( |
||||||
|
"PlatformVersion", |
||||||
|
"PlexMediaSource", |
||||||
|
"TEXT", |
||||||
|
nullable: true); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||||
|
{ |
||||||
|
migrationBuilder.DropColumn( |
||||||
|
"Platform", |
||||||
|
"PlexMediaSource"); |
||||||
|
|
||||||
|
migrationBuilder.DropColumn( |
||||||
|
"PlatformVersion", |
||||||
|
"PlexMediaSource"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
using System.Runtime.InteropServices; |
||||||
|
using ErsatzTV.Core.Interfaces.Runtime; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Runtime |
||||||
|
{ |
||||||
|
public class RuntimeInfo : IRuntimeInfo |
||||||
|
{ |
||||||
|
public bool IsOSPlatform(OSPlatform osPlatform) => RuntimeInformation.IsOSPlatform(osPlatform); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue