using System.Runtime.InteropServices; using System.Text.RegularExpressions; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Interfaces.Plex; using ErsatzTV.Core.Interfaces.Repositories; using ErsatzTV.FFmpeg.Runtime; using Microsoft.Extensions.Logging; namespace ErsatzTV.Core.Plex; public class PlexPathReplacementService : IPlexPathReplacementService { private readonly ILogger _logger; private readonly IMediaSourceRepository _mediaSourceRepository; private readonly IRuntimeInfo _runtimeInfo; public PlexPathReplacementService( IMediaSourceRepository mediaSourceRepository, IRuntimeInfo runtimeInfo, ILogger logger) { _mediaSourceRepository = mediaSourceRepository; _runtimeInfo = runtimeInfo; _logger = logger; } public async Task GetReplacementPlexPath(int libraryPathId, string path, bool log = true) { List replacements = await _mediaSourceRepository.GetPlexPathReplacementsByLibraryId(libraryPathId); return GetReplacementPlexPath(replacements, path, log); } public string GetReplacementPlexPath(List pathReplacements, string path, bool log = true) { Option maybeReplacement = pathReplacements .SingleOrDefault( r => { if (string.IsNullOrWhiteSpace(r.PlexPath)) { return false; } string separatorChar = IsWindows(r.PlexMediaSource) ? @"\" : @"/"; string prefix = r.PlexPath.EndsWith(separatorChar, StringComparison.OrdinalIgnoreCase) ? r.PlexPath : r.PlexPath + separatorChar; return path.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); }); foreach (PlexPathReplacement replacement in maybeReplacement) { string finalPath = Regex.Replace(path, Regex.Escape(replacement.PlexPath), Regex.Replace(replacement.LocalPath ?? string.Empty, "\\$[0-9]+", @"$$$0"), RegexOptions.IgnoreCase); if (IsWindows(replacement.PlexMediaSource) && !_runtimeInfo.IsOSPlatform(OSPlatform.Windows)) { finalPath = finalPath.Replace(@"\", @"/"); } else if (!IsWindows(replacement.PlexMediaSource) && _runtimeInfo.IsOSPlatform(OSPlatform.Windows)) { finalPath = finalPath.Replace(@"/", @"\"); } if (log) { _logger.LogInformation( "Replacing plex path {PlexPath} with {LocalPath} resulting in {FinalPath}", replacement.PlexPath, replacement.LocalPath, finalPath); } return finalPath; } return path; } private static bool IsWindows(PlexMediaSource plexMediaSource) => plexMediaSource.Platform.Equals("windows", StringComparison.OrdinalIgnoreCase); }