fix editorconfig and run code cleanup (#2324)
* fix formatting rules * reformat ersatztv * reformat ersatztv.application * reformat ersatztv.core * refactor ersatztv.core.tests * reformat ersatztv.ffmpeg * reformat ersatztv.ffmpeg.tests * reformat ersatztv.infrastructure * cleanup infra mysql * cleanup infra sqlite * cleanup infra tests * cleanup ersatztv.scanner * cleanup ersatztv.scanner.tests * sln cleanup * update dependencies
This commit is contained in:
@@ -3,4 +3,4 @@ using ErsatzTV.Core;
|
||||
namespace ErsatzTV.Scanner.Application.Emby;
|
||||
|
||||
public record SynchronizeEmbyShowById(int EmbyLibraryId, int ShowId, bool DeepScan)
|
||||
: IRequest<Either<BaseError, string>>;
|
||||
: IRequest<Either<BaseError, string>>;
|
||||
|
||||
@@ -11,9 +11,9 @@ public class SynchronizeEmbyShowByIdHandler : IRequestHandler<SynchronizeEmbySho
|
||||
{
|
||||
private readonly IEmbySecretStore _embySecretStore;
|
||||
private readonly IEmbyTelevisionLibraryScanner _embyTelevisionLibraryScanner;
|
||||
private readonly IEmbyTelevisionRepository _embyTelevisionRepository;
|
||||
private readonly ILogger<SynchronizeEmbyShowByIdHandler> _logger;
|
||||
private readonly IMediaSourceRepository _mediaSourceRepository;
|
||||
private readonly IEmbyTelevisionRepository _embyTelevisionRepository;
|
||||
|
||||
public SynchronizeEmbyShowByIdHandler(
|
||||
IMediaSourceRepository mediaSourceRepository,
|
||||
@@ -119,7 +119,8 @@ public class SynchronizeEmbyShowByIdHandler : IRequestHandler<SynchronizeEmbySho
|
||||
private Task<Validation<BaseError, EmbyShowTitleItemIdResult>> EmbyShowMustExist(
|
||||
SynchronizeEmbyShowById request) =>
|
||||
_embyTelevisionRepository.GetShowTitleItemId(request.EmbyLibraryId, request.ShowId)
|
||||
.Map(v => v.ToValidation<BaseError>($"Jellyfin show {request.ShowId} does not exist in library {request.EmbyLibraryId}."));
|
||||
.Map(v => v.ToValidation<BaseError>(
|
||||
$"Jellyfin show {request.ShowId} does not exist in library {request.EmbyLibraryId}."));
|
||||
|
||||
private record RequestParameters(
|
||||
ConnectionParameters ConnectionParameters,
|
||||
@@ -132,4 +133,4 @@ public class SynchronizeEmbyShowByIdHandler : IRequestHandler<SynchronizeEmbySho
|
||||
{
|
||||
public string? ApiKey { get; init; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ using ErsatzTV.Core;
|
||||
namespace ErsatzTV.Scanner.Application.Jellyfin;
|
||||
|
||||
public record SynchronizeJellyfinShowById(int JellyfinLibraryId, int ShowId, bool DeepScan)
|
||||
: IRequest<Either<BaseError, string>>;
|
||||
: IRequest<Either<BaseError, string>>;
|
||||
|
||||
+8
-5
@@ -7,13 +7,14 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ErsatzTV.Scanner.Application.Jellyfin;
|
||||
|
||||
public class SynchronizeJellyfinShowByIdHandler : IRequestHandler<SynchronizeJellyfinShowById, Either<BaseError, string>>
|
||||
public class
|
||||
SynchronizeJellyfinShowByIdHandler : IRequestHandler<SynchronizeJellyfinShowById, Either<BaseError, string>>
|
||||
{
|
||||
private readonly IJellyfinSecretStore _jellyfinSecretStore;
|
||||
private readonly IJellyfinTelevisionLibraryScanner _jellyfinTelevisionLibraryScanner;
|
||||
private readonly IJellyfinTelevisionRepository _jellyfinTelevisionRepository;
|
||||
private readonly ILogger<SynchronizeJellyfinShowByIdHandler> _logger;
|
||||
private readonly IMediaSourceRepository _mediaSourceRepository;
|
||||
private readonly IJellyfinTelevisionRepository _jellyfinTelevisionRepository;
|
||||
|
||||
public SynchronizeJellyfinShowByIdHandler(
|
||||
IMediaSourceRepository mediaSourceRepository,
|
||||
@@ -71,7 +72,8 @@ public class SynchronizeJellyfinShowByIdHandler : IRequestHandler<SynchronizeJel
|
||||
}
|
||||
|
||||
private async Task<Validation<BaseError, RequestParameters>> Validate(SynchronizeJellyfinShowById request) =>
|
||||
(await ValidateConnection(request), await JellyfinLibraryMustExist(request), await JellyfinShowMustExist(request))
|
||||
(await ValidateConnection(request), await JellyfinLibraryMustExist(request),
|
||||
await JellyfinShowMustExist(request))
|
||||
.Apply((connectionParameters, jellyfinLibrary, showTitleItemId) =>
|
||||
new RequestParameters(
|
||||
connectionParameters,
|
||||
@@ -119,7 +121,8 @@ public class SynchronizeJellyfinShowByIdHandler : IRequestHandler<SynchronizeJel
|
||||
private Task<Validation<BaseError, JellyfinShowTitleItemIdResult>> JellyfinShowMustExist(
|
||||
SynchronizeJellyfinShowById request) =>
|
||||
_jellyfinTelevisionRepository.GetShowTitleItemId(request.JellyfinLibraryId, request.ShowId)
|
||||
.Map(v => v.ToValidation<BaseError>($"Jellyfin show {request.ShowId} does not exist in library {request.JellyfinLibraryId}."));
|
||||
.Map(v => v.ToValidation<BaseError>(
|
||||
$"Jellyfin show {request.ShowId} does not exist in library {request.JellyfinLibraryId}."));
|
||||
|
||||
private record RequestParameters(
|
||||
ConnectionParameters ConnectionParameters,
|
||||
@@ -132,4 +135,4 @@ public class SynchronizeJellyfinShowByIdHandler : IRequestHandler<SynchronizeJel
|
||||
{
|
||||
public string? ApiKey { get; init; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ public class ScanLocalLibraryHandler : IRequestHandler<ScanLocalLibrary, Either<
|
||||
{
|
||||
private readonly IConfigElementRepository _configElementRepository;
|
||||
private readonly IImageFolderScanner _imageFolderScanner;
|
||||
private readonly IRemoteStreamFolderScanner _remoteStreamFolderScanner;
|
||||
private readonly ILibraryRepository _libraryRepository;
|
||||
private readonly ILogger<ScanLocalLibraryHandler> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IMovieFolderScanner _movieFolderScanner;
|
||||
private readonly IMusicVideoFolderScanner _musicVideoFolderScanner;
|
||||
private readonly IOtherVideoFolderScanner _otherVideoFolderScanner;
|
||||
private readonly IRemoteStreamFolderScanner _remoteStreamFolderScanner;
|
||||
private readonly ISongFolderScanner _songFolderScanner;
|
||||
private readonly ITelevisionFolderScanner _televisionFolderScanner;
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@ using ErsatzTV.Core;
|
||||
namespace ErsatzTV.Scanner.Application.Plex;
|
||||
|
||||
public record SynchronizePlexShowById(int PlexLibraryId, int ShowId, bool DeepScan)
|
||||
: IRequest<Either<BaseError, string>>;
|
||||
: IRequest<Either<BaseError, string>>;
|
||||
|
||||
@@ -10,10 +10,10 @@ namespace ErsatzTV.Scanner.Application.Plex;
|
||||
public class SynchronizePlexShowByIdHandler : IRequestHandler<SynchronizePlexShowById, Either<BaseError, string>>
|
||||
{
|
||||
private readonly ILogger<SynchronizePlexShowByIdHandler> _logger;
|
||||
private readonly IPlexTelevisionRepository _plexTelevisionRepository;
|
||||
private readonly IMediaSourceRepository _mediaSourceRepository;
|
||||
private readonly IPlexSecretStore _plexSecretStore;
|
||||
private readonly IPlexTelevisionLibraryScanner _plexTelevisionLibraryScanner;
|
||||
private readonly IPlexTelevisionRepository _plexTelevisionRepository;
|
||||
|
||||
public SynchronizePlexShowByIdHandler(
|
||||
IPlexTelevisionRepository plexTelevisionRepository,
|
||||
@@ -119,7 +119,8 @@ public class SynchronizePlexShowByIdHandler : IRequestHandler<SynchronizePlexSho
|
||||
private Task<Validation<BaseError, PlexShowTitleKeyResult>> PlexShowMustExist(
|
||||
SynchronizePlexShowById request) =>
|
||||
_plexTelevisionRepository.GetShowTitleKey(request.PlexLibraryId, request.ShowId)
|
||||
.Map(v => v.ToValidation<BaseError>($"Plex show {request.ShowId} does not exist in library {request.PlexLibraryId}."));
|
||||
.Map(v => v.ToValidation<BaseError>(
|
||||
$"Plex show {request.ShowId} does not exist in library {request.PlexLibraryId}."));
|
||||
|
||||
private record RequestParameters(
|
||||
ConnectionParameters ConnectionParameters,
|
||||
@@ -132,4 +133,4 @@ public class SynchronizePlexShowByIdHandler : IRequestHandler<SynchronizePlexSho
|
||||
{
|
||||
public PlexServerAuthToken? PlexServerAuthToken { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Emby;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Emby;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -76,6 +76,60 @@ public class EmbyTelevisionLibraryScanner : MediaServerTelevisionLibraryScanner<
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<Either<BaseError, Unit>> ScanSingleShow(
|
||||
string address,
|
||||
string apiKey,
|
||||
EmbyLibrary library,
|
||||
string showId,
|
||||
string showTitle,
|
||||
bool deepScan,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<EmbyPathReplacement> pathReplacements =
|
||||
await _mediaSourceRepository.GetEmbyPathReplacements(library.MediaSourceId);
|
||||
|
||||
string GetLocalPath(EmbyEpisode episode)
|
||||
{
|
||||
return _pathReplacementService.GetReplacementEmbyPath(
|
||||
pathReplacements,
|
||||
episode.GetHeadVersion().MediaFiles.Head().Path,
|
||||
false);
|
||||
}
|
||||
|
||||
// Search for the specific show
|
||||
Either<BaseError, Option<EmbyShow>> searchResult = await _embyApiClient.GetSingleShow(
|
||||
address,
|
||||
apiKey,
|
||||
library,
|
||||
showId);
|
||||
|
||||
return await searchResult.Match(
|
||||
async maybeShow =>
|
||||
{
|
||||
foreach (EmbyShow show in maybeShow)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Found show '{ShowTitle}' with id {ShowId}, starting targeted scan",
|
||||
showTitle,
|
||||
show.ItemId);
|
||||
|
||||
return await ScanSingleShowInternal(
|
||||
_televisionRepository,
|
||||
new EmbyConnectionParameters(address, apiKey),
|
||||
library,
|
||||
show,
|
||||
GetLocalPath,
|
||||
deepScan,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogWarning("No show found with id {ShowId} in library {LibraryName}", showId, library.Name);
|
||||
|
||||
return Right<BaseError, Unit>(Unit.Default);
|
||||
},
|
||||
error => Task.FromResult<Either<BaseError, Unit>>(error));
|
||||
}
|
||||
|
||||
protected override IAsyncEnumerable<Tuple<EmbyShow, int>> GetShowLibraryItems(
|
||||
EmbyConnectionParameters connectionParameters,
|
||||
EmbyLibrary library) =>
|
||||
@@ -186,58 +240,6 @@ public class EmbyTelevisionLibraryScanner : MediaServerTelevisionLibraryScanner<
|
||||
EpisodeMetadata fullMetadata) =>
|
||||
Task.FromResult<Either<BaseError, MediaItemScanResult<EmbyEpisode>>>(result);
|
||||
|
||||
public async Task<Either<BaseError, Unit>> ScanSingleShow(
|
||||
string address,
|
||||
string apiKey,
|
||||
EmbyLibrary library,
|
||||
string showId,
|
||||
string showTitle,
|
||||
bool deepScan,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<EmbyPathReplacement> pathReplacements =
|
||||
await _mediaSourceRepository.GetEmbyPathReplacements(library.MediaSourceId);
|
||||
|
||||
string GetLocalPath(EmbyEpisode episode)
|
||||
{
|
||||
return _pathReplacementService.GetReplacementEmbyPath(
|
||||
pathReplacements,
|
||||
episode.GetHeadVersion().MediaFiles.Head().Path,
|
||||
false);
|
||||
}
|
||||
|
||||
// Search for the specific show
|
||||
Either<BaseError, Option<EmbyShow>> searchResult = await _embyApiClient.GetSingleShow(
|
||||
address,
|
||||
apiKey,
|
||||
library,
|
||||
showId);
|
||||
|
||||
return await searchResult.Match(
|
||||
async maybeShow =>
|
||||
{
|
||||
foreach (var show in maybeShow)
|
||||
{
|
||||
_logger.LogInformation("Found show '{ShowTitle}' with id {ShowId}, starting targeted scan",
|
||||
showTitle, show.ItemId);
|
||||
|
||||
return await ScanSingleShowInternal(
|
||||
_televisionRepository,
|
||||
new EmbyConnectionParameters(address, apiKey),
|
||||
library,
|
||||
show,
|
||||
GetLocalPath,
|
||||
deepScan,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogWarning("No show found with id {ShowId} in library {LibraryName}", showId, library.Name);
|
||||
|
||||
return Right<BaseError, Unit>(Unit.Default);
|
||||
},
|
||||
error => Task.FromResult<Either<BaseError, Unit>>(error));
|
||||
}
|
||||
|
||||
private async Task<Either<BaseError, Unit>> ScanSingleShowInternal(
|
||||
IEmbyTelevisionRepository televisionRepository,
|
||||
EmbyConnectionParameters connectionParameters,
|
||||
|
||||
@@ -5,4 +5,4 @@ namespace ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
public interface ILocalChaptersProvider : IDisposable
|
||||
{
|
||||
Task<bool> UpdateChapters(MediaItem mediaItem, Option<string> localPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Jellyfin;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Jellyfin;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Jellyfin;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Jellyfin;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -77,6 +77,60 @@ public class JellyfinTelevisionLibraryScanner : MediaServerTelevisionLibraryScan
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<Either<BaseError, Unit>> ScanSingleShow(
|
||||
string address,
|
||||
string apiKey,
|
||||
JellyfinLibrary library,
|
||||
string showId,
|
||||
string showTitle,
|
||||
bool deepScan,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<JellyfinPathReplacement> pathReplacements =
|
||||
await _mediaSourceRepository.GetJellyfinPathReplacements(library.MediaSourceId);
|
||||
|
||||
string GetLocalPath(JellyfinEpisode episode)
|
||||
{
|
||||
return _pathReplacementService.GetReplacementJellyfinPath(
|
||||
pathReplacements,
|
||||
episode.GetHeadVersion().MediaFiles.Head().Path,
|
||||
false);
|
||||
}
|
||||
|
||||
// Search for the specific show
|
||||
Either<BaseError, Option<JellyfinShow>> searchResult = await _jellyfinApiClient.GetSingleShow(
|
||||
address,
|
||||
apiKey,
|
||||
library,
|
||||
showId);
|
||||
|
||||
return await searchResult.Match(
|
||||
async maybeShow =>
|
||||
{
|
||||
foreach (JellyfinShow show in maybeShow)
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Found show '{ShowTitle}' with id {ShowId}, starting targeted scan",
|
||||
showTitle,
|
||||
show.ItemId);
|
||||
|
||||
return await ScanSingleShowInternal(
|
||||
_televisionRepository,
|
||||
new JellyfinConnectionParameters(address, apiKey, library.MediaSourceId),
|
||||
library,
|
||||
show,
|
||||
GetLocalPath,
|
||||
deepScan,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogWarning("No show found with id {ShowId} in library {LibraryName}", showId, library.Name);
|
||||
|
||||
return Right<BaseError, Unit>(Unit.Default);
|
||||
},
|
||||
error => Task.FromResult<Either<BaseError, Unit>>(error));
|
||||
}
|
||||
|
||||
protected override IAsyncEnumerable<Tuple<JellyfinShow, int>> GetShowLibraryItems(
|
||||
JellyfinConnectionParameters connectionParameters,
|
||||
JellyfinLibrary library) =>
|
||||
@@ -185,58 +239,6 @@ public class JellyfinTelevisionLibraryScanner : MediaServerTelevisionLibraryScan
|
||||
EpisodeMetadata fullMetadata) =>
|
||||
Task.FromResult<Either<BaseError, MediaItemScanResult<JellyfinEpisode>>>(result);
|
||||
|
||||
public async Task<Either<BaseError, Unit>> ScanSingleShow(
|
||||
string address,
|
||||
string apiKey,
|
||||
JellyfinLibrary library,
|
||||
string showId,
|
||||
string showTitle,
|
||||
bool deepScan,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<JellyfinPathReplacement> pathReplacements =
|
||||
await _mediaSourceRepository.GetJellyfinPathReplacements(library.MediaSourceId);
|
||||
|
||||
string GetLocalPath(JellyfinEpisode episode)
|
||||
{
|
||||
return _pathReplacementService.GetReplacementJellyfinPath(
|
||||
pathReplacements,
|
||||
episode.GetHeadVersion().MediaFiles.Head().Path,
|
||||
false);
|
||||
}
|
||||
|
||||
// Search for the specific show
|
||||
Either<BaseError, Option<JellyfinShow>> searchResult = await _jellyfinApiClient.GetSingleShow(
|
||||
address,
|
||||
apiKey,
|
||||
library,
|
||||
showId);
|
||||
|
||||
return await searchResult.Match(
|
||||
async maybeShow =>
|
||||
{
|
||||
foreach (var show in maybeShow)
|
||||
{
|
||||
_logger.LogInformation("Found show '{ShowTitle}' with id {ShowId}, starting targeted scan",
|
||||
showTitle, show.ItemId);
|
||||
|
||||
return await ScanSingleShowInternal(
|
||||
_televisionRepository,
|
||||
new JellyfinConnectionParameters(address, apiKey, library.MediaSourceId),
|
||||
library,
|
||||
show,
|
||||
GetLocalPath,
|
||||
deepScan,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogWarning("No show found with id {ShowId} in library {LibraryName}", showId, library.Name);
|
||||
|
||||
return Right<BaseError, Unit>(Unit.Default);
|
||||
},
|
||||
error => Task.FromResult<Either<BaseError, Unit>>(error));
|
||||
}
|
||||
|
||||
private async Task<Either<BaseError, Unit>> ScanSingleShowInternal(
|
||||
IJellyfinTelevisionRepository televisionRepository,
|
||||
JellyfinConnectionParameters connectionParameters,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
|
||||
namespace ErsatzTV.Scanner.Core.Metadata;
|
||||
|
||||
@@ -51,6 +51,12 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public List<MediaChapter> LocateExternalChapters(string mediaItemPath)
|
||||
{
|
||||
var result = new List<MediaChapter>();
|
||||
@@ -124,7 +130,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
var chapters = new List<MediaChapter>();
|
||||
|
||||
XmlNodeList? chapterAtoms = chaptersNode.SelectNodes(".//ChapterAtom") ??
|
||||
chaptersNode.SelectNodes(".//chapteratom");
|
||||
chaptersNode.SelectNodes(".//chapteratom");
|
||||
|
||||
if (chapterAtoms == null)
|
||||
{
|
||||
@@ -134,7 +140,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
long chapterId = 0;
|
||||
foreach (XmlNode chapterAtom in chapterAtoms)
|
||||
{
|
||||
var chapter = ParseChapterAtom(chapterAtom, chapterId++);
|
||||
MediaChapter? chapter = ParseChapterAtom(chapterAtom, chapterId++);
|
||||
if (chapter != null)
|
||||
{
|
||||
chapters.Add(chapter);
|
||||
@@ -143,7 +149,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
|
||||
chapters.Sort((a, b) => a.StartTime.CompareTo(b.StartTime));
|
||||
|
||||
for (int i = 0; i < chapters.Count; i++)
|
||||
for (var i = 0; i < chapters.Count; i++)
|
||||
{
|
||||
chapters[i].ChapterId = i;
|
||||
}
|
||||
@@ -154,7 +160,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
private static MediaChapter? ParseChapterAtom(XmlNode chapterAtom, long chapterId)
|
||||
{
|
||||
XmlNode? startNode = chapterAtom.SelectSingleNode(".//ChapterTimeStart") ??
|
||||
chapterAtom.SelectSingleNode(".//chaptertimestart");
|
||||
chapterAtom.SelectSingleNode(".//chaptertimestart");
|
||||
|
||||
if (startNode?.InnerText == null)
|
||||
{
|
||||
@@ -168,7 +174,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
|
||||
TimeSpan endTime = TimeSpan.Zero;
|
||||
XmlNode? endNode = chapterAtom.SelectSingleNode(".//ChapterTimeEnd") ??
|
||||
chapterAtom.SelectSingleNode(".//chaptertimeend");
|
||||
chapterAtom.SelectSingleNode(".//chaptertimeend");
|
||||
|
||||
if (endNode?.InnerText != null)
|
||||
{
|
||||
@@ -177,9 +183,9 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
|
||||
string title = string.Empty;
|
||||
XmlNode? titleNode = chapterAtom.SelectSingleNode(".//ChapterString") ??
|
||||
chapterAtom.SelectSingleNode(".//ChapString") ??
|
||||
chapterAtom.SelectSingleNode(".//chapterstring") ??
|
||||
chapterAtom.SelectSingleNode(".//chapstring");
|
||||
chapterAtom.SelectSingleNode(".//ChapString") ??
|
||||
chapterAtom.SelectSingleNode(".//chapterstring") ??
|
||||
chapterAtom.SelectSingleNode(".//chapstring");
|
||||
|
||||
if (titleNode?.InnerText != null)
|
||||
{
|
||||
@@ -212,7 +218,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
}
|
||||
|
||||
// Handle time format HH:MM:SS.mmm or HH:MM:SS,mmm
|
||||
var timeFormats = new Regex[]
|
||||
var timeFormats = new[]
|
||||
{
|
||||
GetParseFullTimeCodeRegex(),
|
||||
GetParseTimeCodeNoMilliRegex()
|
||||
@@ -220,14 +226,14 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
|
||||
foreach (Regex pattern in timeFormats)
|
||||
{
|
||||
var match = pattern.Match(timeString);
|
||||
Match match = pattern.Match(timeString);
|
||||
if (match.Success)
|
||||
{
|
||||
if (int.TryParse(match.Groups[1].Value, out int hours) &&
|
||||
int.TryParse(match.Groups[2].Value, out int minutes) &&
|
||||
int.TryParse(match.Groups[3].Value, out int seconds))
|
||||
{
|
||||
int milliseconds = 0;
|
||||
var milliseconds = 0;
|
||||
if (match.Groups.Count > 4 && !int.TryParse(match.Groups[4].Value, out milliseconds))
|
||||
{
|
||||
milliseconds = 0;
|
||||
@@ -242,12 +248,6 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
@@ -258,6 +258,7 @@ public partial class LocalChaptersProvider : ILocalChaptersProvider
|
||||
|
||||
[GeneratedRegex(@"^(\d{1,2}):(\d{2}):(\d{2})[\.,](\d{3})$")]
|
||||
private static partial Regex GetParseFullTimeCodeRegex();
|
||||
|
||||
[GeneratedRegex(@"^(\d{1,2}):(\d{2}):(\d{2})$")]
|
||||
private static partial Regex GetParseTimeCodeNoMilliRegex();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ public class LocalMetadataProvider : ILocalMetadataProvider
|
||||
private readonly IEpisodeNfoReader _episodeNfoReader;
|
||||
private readonly IFallbackMetadataProvider _fallbackMetadataProvider;
|
||||
private readonly IImageRepository _imageRepository;
|
||||
private readonly IRemoteStreamRepository _remoteStreamRepository;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalStatisticsProvider _localStatisticsProvider;
|
||||
private readonly ILogger<LocalMetadataProvider> _logger;
|
||||
@@ -34,6 +33,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider
|
||||
private readonly IMusicVideoRepository _musicVideoRepository;
|
||||
private readonly IOtherVideoNfoReader _otherVideoNfoReader;
|
||||
private readonly IOtherVideoRepository _otherVideoRepository;
|
||||
private readonly IRemoteStreamRepository _remoteStreamRepository;
|
||||
private readonly IShowNfoReader _showNfoReader;
|
||||
private readonly ISongRepository _songRepository;
|
||||
private readonly ITelevisionRepository _televisionRepository;
|
||||
@@ -189,7 +189,7 @@ public class LocalMetadataProvider : ILocalMetadataProvider
|
||||
string diff = Path.GetRelativePath(parent, folder);
|
||||
|
||||
var tags = diff.Split(Path.DirectorySeparatorChar)
|
||||
.Filter(t => metadata.Tags.Any(mt => mt.Name == t) == false)
|
||||
.Filter(t => metadata.Tags.All(mt => mt.Name != t))
|
||||
.Map(t => new Tag { Name = t })
|
||||
.ToList();
|
||||
|
||||
@@ -224,16 +224,13 @@ public class LocalMetadataProvider : ILocalMetadataProvider
|
||||
return await RefreshFallbackMetadata(image);
|
||||
}
|
||||
|
||||
public async Task<bool> RefreshTagMetadata(RemoteStream remoteStream)
|
||||
{
|
||||
public async Task<bool> RefreshTagMetadata(RemoteStream remoteStream) =>
|
||||
// Option<RemoteStreamMetadata> maybeMetadata = LoadRemoteStreamMetadata(remoteStream);
|
||||
// foreach (RemoteStreamMetadata metadata in maybeMetadata)
|
||||
// {
|
||||
// return await ApplyMetadataUpdate(remoteStream, metadata);
|
||||
// }
|
||||
|
||||
return await RefreshFallbackMetadata(remoteStream);
|
||||
}
|
||||
await RefreshFallbackMetadata(remoteStream);
|
||||
|
||||
public Task<bool> RefreshFallbackMetadata(Movie movie) =>
|
||||
ApplyMetadataUpdate(movie, _fallbackMetadataProvider.GetFallbackMetadata(movie));
|
||||
@@ -1471,11 +1468,12 @@ public class LocalMetadataProvider : ILocalMetadataProvider
|
||||
var tags = nfo.Tags.Map(t => new Tag { Name = t }).ToList();
|
||||
foreach (string country in nfo.Countries)
|
||||
{
|
||||
tags.Add(new Tag
|
||||
{
|
||||
Name = country,
|
||||
ExternalTypeId = Tag.NfoCountryTypeId
|
||||
});
|
||||
tags.Add(
|
||||
new Tag
|
||||
{
|
||||
Name = country,
|
||||
ExternalTypeId = Tag.NfoCountryTypeId
|
||||
});
|
||||
}
|
||||
|
||||
return new MovieMetadata
|
||||
|
||||
@@ -19,8 +19,8 @@ public abstract class MediaServerMovieLibraryScanner<TConnectionParameters, TLib
|
||||
where TMovie : Movie
|
||||
where TEtag : MediaServerItemEtag
|
||||
{
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IMetadataRepository _metadataRepository;
|
||||
@@ -101,7 +101,7 @@ public abstract class MediaServerMovieLibraryScanner<TConnectionParameters, TLib
|
||||
|
||||
string localPath = getLocalPath(incoming);
|
||||
|
||||
if (await ShouldScanItem(movieRepository, library, existingMovies, incoming, localPath, deepScan) == false)
|
||||
if (!await ShouldScanItem(movieRepository, library, existingMovies, incoming, localPath, deepScan))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ using ErsatzTV.Core.Errors;
|
||||
using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.MediaSources;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ErsatzTV.Scanner.Core.Metadata;
|
||||
@@ -19,8 +19,8 @@ public abstract class MediaServerOtherVideoLibraryScanner<TConnectionParameters,
|
||||
where TOtherVideo : OtherVideo
|
||||
where TEtag : MediaServerItemEtag
|
||||
{
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IMetadataRepository _metadataRepository;
|
||||
@@ -102,13 +102,13 @@ public abstract class MediaServerOtherVideoLibraryScanner<TConnectionParameters,
|
||||
|
||||
string localPath = getLocalPath(incoming);
|
||||
|
||||
if (await ShouldScanItem(
|
||||
if (!await ShouldScanItem(
|
||||
otherVideoRepository,
|
||||
library,
|
||||
existingOtherVideos,
|
||||
incoming,
|
||||
localPath,
|
||||
deepScan) == false)
|
||||
deepScan))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ using ErsatzTV.Core.Errors;
|
||||
using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.MediaSources;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ErsatzTV.Scanner.Core.Metadata;
|
||||
@@ -21,8 +21,8 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,
|
||||
where TEpisode : Episode
|
||||
where TEtag : MediaServerItemEtag
|
||||
{
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IMetadataRepository _metadataRepository;
|
||||
@@ -198,18 +198,16 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,
|
||||
Func<TEpisode, string> getLocalPath,
|
||||
IAsyncEnumerable<Tuple<TShow, int>> showEntries,
|
||||
bool deepScan,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await InternalScanLibrary(
|
||||
CancellationToken cancellationToken) =>
|
||||
await InternalScanLibrary(
|
||||
televisionRepository,
|
||||
connectionParameters,
|
||||
library,
|
||||
getLocalPath,
|
||||
showEntries,
|
||||
deepScan,
|
||||
cleanupFileNotFoundItems: true,
|
||||
true,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
protected async Task<Either<BaseError, Unit>> ScanLibraryWithoutCleanup(
|
||||
IMediaServerTelevisionRepository<TLibrary, TShow, TSeason, TEpisode, TEtag> televisionRepository,
|
||||
@@ -218,18 +216,16 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,
|
||||
Func<TEpisode, string> getLocalPath,
|
||||
IAsyncEnumerable<Tuple<TShow, int>> showEntries,
|
||||
bool deepScan,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await InternalScanLibrary(
|
||||
CancellationToken cancellationToken) =>
|
||||
await InternalScanLibrary(
|
||||
televisionRepository,
|
||||
connectionParameters,
|
||||
library,
|
||||
getLocalPath,
|
||||
showEntries,
|
||||
deepScan,
|
||||
cleanupFileNotFoundItems: false,
|
||||
false,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
protected abstract IAsyncEnumerable<Tuple<TSeason, int>> GetSeasonLibraryItems(
|
||||
TLibrary library,
|
||||
@@ -408,7 +404,7 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,
|
||||
incomingItemIds.Add(MediaServerItemId(incoming));
|
||||
|
||||
string localPath = getLocalPath(incoming);
|
||||
if (await ShouldScanItem(
|
||||
if (!await ShouldScanItem(
|
||||
televisionRepository,
|
||||
library,
|
||||
show,
|
||||
@@ -416,7 +412,7 @@ public abstract class MediaServerTelevisionLibraryScanner<TConnectionParameters,
|
||||
existingEpisodes,
|
||||
incoming,
|
||||
localPath,
|
||||
deepScan) == false)
|
||||
deepScan))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ public class MovieFolderScanner : LocalFolderScanner, IMovieFolderScanner
|
||||
{
|
||||
private readonly IClient _client;
|
||||
private readonly ILibraryRepository _libraryRepository;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalMetadataProvider _localMetadataProvider;
|
||||
private readonly ILocalSubtitlesProvider _localSubtitlesProvider;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILogger<MovieFolderScanner> _logger;
|
||||
private readonly IMediaItemRepository _mediaItemRepository;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
@@ -21,10 +21,10 @@ public class MusicVideoFolderScanner : LocalFolderScanner, IMusicVideoFolderScan
|
||||
private readonly IArtistRepository _artistRepository;
|
||||
private readonly IClient _client;
|
||||
private readonly ILibraryRepository _libraryRepository;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalMetadataProvider _localMetadataProvider;
|
||||
private readonly ILocalSubtitlesProvider _localSubtitlesProvider;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILogger<MusicVideoFolderScanner> _logger;
|
||||
private readonly IMediaItemRepository _mediaItemRepository;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
@@ -49,7 +49,11 @@ public abstract class NfoReader<T> : NfoReaderBase
|
||||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error reading string content from NFO {ElementName} file {FileName}", reader.Name, fileName);
|
||||
_logger.LogWarning(
|
||||
ex,
|
||||
"Error reading string content from NFO {ElementName} file {FileName}",
|
||||
reader.Name,
|
||||
fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +68,11 @@ public abstract class NfoReader<T> : NfoReaderBase
|
||||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error reading int content from NFO {ElementName} file {FileName}", reader.Name, fileName);
|
||||
_logger.LogWarning(
|
||||
ex,
|
||||
"Error reading int content from NFO {ElementName} file {FileName}",
|
||||
reader.Name,
|
||||
fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +89,11 @@ public abstract class NfoReader<T> : NfoReaderBase
|
||||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error reading date content from NFO {ElementName} file {FileName}", reader.Name, fileName);
|
||||
_logger.LogWarning(
|
||||
ex,
|
||||
"Error reading date content from NFO {ElementName} file {FileName}",
|
||||
reader.Name,
|
||||
fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +135,11 @@ public abstract class NfoReader<T> : NfoReaderBase
|
||||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error reading actor content from NFO {ElementName} file {FileName}", reader.Name, fileName);
|
||||
_logger.LogWarning(
|
||||
ex,
|
||||
"Error reading actor content from NFO {ElementName} file {FileName}",
|
||||
reader.Name,
|
||||
fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +162,11 @@ public abstract class NfoReader<T> : NfoReaderBase
|
||||
}
|
||||
catch (XmlException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error reading uniqueid content from NFO {ElementName} file {FileName}", reader.Name, fileName);
|
||||
_logger.LogWarning(
|
||||
ex,
|
||||
"Error reading uniqueid content from NFO {ElementName} file {FileName}",
|
||||
reader.Name,
|
||||
fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ public class OtherVideoNfoReader : NfoReader<OtherVideoNfo>, IOtherVideoNfoReade
|
||||
await ReadStringContent(
|
||||
reader,
|
||||
nfo,
|
||||
(movie, contentRating) => movie.ContentRating = contentRating, fileName);
|
||||
(movie, contentRating) => movie.ContentRating = contentRating,
|
||||
fileName);
|
||||
break;
|
||||
case "premiered":
|
||||
await ReadDateTimeContent(
|
||||
|
||||
@@ -20,10 +20,10 @@ public class OtherVideoFolderScanner : LocalFolderScanner, IOtherVideoFolderScan
|
||||
{
|
||||
private readonly IClient _client;
|
||||
private readonly ILibraryRepository _libraryRepository;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalMetadataProvider _localMetadataProvider;
|
||||
private readonly ILocalSubtitlesProvider _localSubtitlesProvider;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILogger<OtherVideoFolderScanner> _logger;
|
||||
private readonly IMediaItemRepository _mediaItemRepository;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace ErsatzTV.Scanner.Core.Metadata;
|
||||
public class RemoteStreamFolderScanner : LocalFolderScanner, IRemoteStreamFolderScanner
|
||||
{
|
||||
private readonly IClient _client;
|
||||
private readonly IRemoteStreamRepository _remoteStreamRepository;
|
||||
private readonly ILibraryRepository _libraryRepository;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalMetadataProvider _localMetadataProvider;
|
||||
private readonly ILogger<RemoteStreamFolderScanner> _logger;
|
||||
private readonly IMediaItemRepository _mediaItemRepository;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly IRemoteStreamRepository _remoteStreamRepository;
|
||||
|
||||
public RemoteStreamFolderScanner(
|
||||
ILocalFileSystem localFileSystem,
|
||||
@@ -126,7 +126,8 @@ public class RemoteStreamFolderScanner : LocalFolderScanner, IRemoteStreamFolder
|
||||
cancellationToken);
|
||||
|
||||
string remoteStreamFolder = folderQueue.Dequeue();
|
||||
Option<int> maybeParentFolder = await _libraryRepository.GetParentFolderId(libraryPath, remoteStreamFolder);
|
||||
Option<int> maybeParentFolder =
|
||||
await _libraryRepository.GetParentFolderId(libraryPath, remoteStreamFolder);
|
||||
|
||||
foldersCompleted++;
|
||||
|
||||
@@ -155,7 +156,9 @@ public class RemoteStreamFolderScanner : LocalFolderScanner, IRemoteStreamFolder
|
||||
{
|
||||
if (allFiles.Any(allTrashedItems.Contains))
|
||||
{
|
||||
_logger.LogDebug("Previously trashed items are now present in folder {Folder}", remoteStreamFolder);
|
||||
_logger.LogDebug(
|
||||
"Previously trashed items are now present in folder {Folder}",
|
||||
remoteStreamFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -281,10 +284,10 @@ public class RemoteStreamFolderScanner : LocalFolderScanner, IRemoteStreamFolder
|
||||
YamlRemoteStreamDefinition definition = deserializer.Deserialize<YamlRemoteStreamDefinition>(yaml);
|
||||
if (!definition.IsLive.HasValue)
|
||||
{
|
||||
return BaseError.New($"Remote stream definition is missing required `is_live` property");
|
||||
return BaseError.New("Remote stream definition is missing required `is_live` property");
|
||||
}
|
||||
|
||||
bool updated = false;
|
||||
var updated = false;
|
||||
if (remoteStream.IsLive != definition.IsLive.Value)
|
||||
{
|
||||
remoteStream.IsLive = definition.IsLive.Value;
|
||||
|
||||
@@ -21,10 +21,10 @@ public class TelevisionFolderScanner : LocalFolderScanner, ITelevisionFolderScan
|
||||
private readonly IClient _client;
|
||||
private readonly IFallbackMetadataProvider _fallbackMetadataProvider;
|
||||
private readonly ILibraryRepository _libraryRepository;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILocalFileSystem _localFileSystem;
|
||||
private readonly ILocalMetadataProvider _localMetadataProvider;
|
||||
private readonly ILocalSubtitlesProvider _localSubtitlesProvider;
|
||||
private readonly ILocalChaptersProvider _localChaptersProvider;
|
||||
private readonly ILogger<TelevisionFolderScanner> _logger;
|
||||
private readonly IMediaItemRepository _mediaItemRepository;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
@@ -4,9 +4,9 @@ using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Plex;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Core.Plex;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ using ErsatzTV.Core.Extensions;
|
||||
using ErsatzTV.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Interfaces.Plex;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Core.Plex;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.Metadata;
|
||||
using ErsatzTV.Scanner.Core.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -120,9 +120,10 @@ public partial class PlexTelevisionLibraryScanner :
|
||||
return await showResult.Match(
|
||||
async maybeShow =>
|
||||
{
|
||||
foreach (var show in maybeShow)
|
||||
foreach (PlexShow show in maybeShow)
|
||||
{
|
||||
_logger.LogInformation("Found show '{ShowTitle}' with key {ShowKey}, starting targeted scan",
|
||||
_logger.LogInformation(
|
||||
"Found show '{ShowTitle}' with key {ShowKey}, starting targeted scan",
|
||||
showTitle,
|
||||
show.Key);
|
||||
|
||||
@@ -144,7 +145,8 @@ public partial class PlexTelevisionLibraryScanner :
|
||||
}
|
||||
|
||||
private async Task<Either<BaseError, Unit>> ScanSingleShowInternal(
|
||||
IMediaServerTelevisionRepository<PlexLibrary, PlexShow, PlexSeason, PlexEpisode, PlexItemEtag> televisionRepository,
|
||||
IMediaServerTelevisionRepository<PlexLibrary, PlexShow, PlexSeason, PlexEpisode, PlexItemEtag>
|
||||
televisionRepository,
|
||||
PlexConnectionParameters connectionParameters,
|
||||
PlexLibrary library,
|
||||
PlexShow targetShow,
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta6.25358.103" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta7.25380.108" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -42,4 +42,4 @@
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -13,7 +13,6 @@ using ErsatzTV.Core.Interfaces.Plex;
|
||||
using ErsatzTV.Core.Interfaces.Repositories;
|
||||
using ErsatzTV.Core.Interfaces.Repositories.Caching;
|
||||
using ErsatzTV.Core.Interfaces.Search;
|
||||
using ErsatzTV.Core.Interfaces.Streaming;
|
||||
using ErsatzTV.Core.Jellyfin;
|
||||
using ErsatzTV.Core.Metadata;
|
||||
using ErsatzTV.Core.Plex;
|
||||
@@ -30,7 +29,6 @@ using ErsatzTV.Infrastructure.Plex;
|
||||
using ErsatzTV.Infrastructure.Runtime;
|
||||
using ErsatzTV.Infrastructure.Search;
|
||||
using ErsatzTV.Infrastructure.Sqlite.Data;
|
||||
using ErsatzTV.Infrastructure.Streaming;
|
||||
using ErsatzTV.Scanner.Core.Emby;
|
||||
using ErsatzTV.Scanner.Core.FFmpeg;
|
||||
using ErsatzTV.Scanner.Core.Interfaces.FFmpeg;
|
||||
|
||||
@@ -34,7 +34,7 @@ public class Worker : BackgroundService
|
||||
string[] arguments = Environment.GetCommandLineArgs().Skip(1).ToArray();
|
||||
|
||||
ParseResult parseResult = rootCommand.Parse(arguments);
|
||||
await parseResult.InvokeAsync(stoppingToken);
|
||||
await parseResult.InvokeAsync(cancellationToken: stoppingToken);
|
||||
|
||||
_appLifetime.StopApplication();
|
||||
}
|
||||
@@ -117,7 +117,9 @@ public class Worker : BackgroundService
|
||||
scanEmbyShowCommand.Arguments.Add(showIdArgument);
|
||||
scanEmbyShowCommand.Options.Add(deepOption);
|
||||
|
||||
var scanJellyfinShowCommand = new Command("scan-jellyfin-show", "Scan a specific TV show in a Jellyfin library");
|
||||
var scanJellyfinShowCommand = new Command(
|
||||
"scan-jellyfin-show",
|
||||
"Scan a specific TV show in a Jellyfin library");
|
||||
scanJellyfinShowCommand.Arguments.Add(libraryIdArgument);
|
||||
scanJellyfinShowCommand.Arguments.Add(showIdArgument);
|
||||
scanJellyfinShowCommand.Options.Add(deepOption);
|
||||
|
||||
Reference in New Issue
Block a user