Compare commits

...
9 changed files with 79 additions and 21 deletions
+1 -1
View File
@@ -98,7 +98,7 @@ namespace ErsatzTV.Core.Metadata
continue;
}
if (_localFileSystem.GetLastWriteTime(movieFolder) < lastScan)
if (allFiles.All(file => _localFileSystem.GetLastWriteTime(file) < lastScan))
{
continue;
}
@@ -156,7 +156,7 @@ namespace ErsatzTV.Core.Plex
PlexMovie existing = result.Item;
MovieMetadata existingMetadata = existing.MovieMetadata.Head();
if (incoming.MovieMetadata.Head().DateUpdated > existingMetadata.DateUpdated)
if (result.IsAdded || incoming.MovieMetadata.Head().DateUpdated > existingMetadata.DateUpdated)
{
_logger.LogDebug(
"Refreshing {Attribute} from {Path}",
@@ -218,7 +218,9 @@ namespace ErsatzTV.Core.Plex
}
foreach (Actor actor in existingMetadata.Actors
.Filter(a => fullMetadata.Actors.All(a2 => a2.Name != a.Name))
.Filter(
a => fullMetadata.Actors.All(
a2 => a2.Name != a.Name || a.Artwork == null && a2.Artwork != null))
.ToList())
{
existingMetadata.Actors.Remove(actor);
@@ -124,7 +124,7 @@ namespace ErsatzTV.Core.Plex
PlexShow existing = result.Item;
ShowMetadata existingMetadata = existing.ShowMetadata.Head();
if (incoming.ShowMetadata.Head().DateUpdated > existingMetadata.DateUpdated)
if (result.IsAdded || incoming.ShowMetadata.Head().DateUpdated > existingMetadata.DateUpdated)
{
Either<BaseError, ShowMetadata> maybeMetadata =
await _plexServerApiClient.GetShowMetadata(
@@ -181,7 +181,9 @@ namespace ErsatzTV.Core.Plex
}
foreach (Actor actor in existingMetadata.Actors
.Filter(a => fullMetadata.Actors.All(a2 => a2.Name != a.Name))
.Filter(
a => fullMetadata.Actors.All(
a2 => a2.Name != a.Name || a.Artwork == null && a2.Artwork != null))
.ToList())
{
existingMetadata.Actors.Remove(actor);
@@ -67,6 +67,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.ThenInclude(mm => mm.Studios)
.Include(i => i.MovieMetadata)
.ThenInclude(mm => mm.Actors)
.ThenInclude(a => a.Artwork)
.Include(i => i.LibraryPath)
.ThenInclude(lp => lp.Library)
.Include(i => i.MediaVersions)
@@ -98,6 +99,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.ThenInclude(mm => mm.Studios)
.Include(i => i.MovieMetadata)
.ThenInclude(mm => mm.Actors)
.ThenInclude(a => a.Artwork)
.Include(i => i.MovieMetadata)
.ThenInclude(mm => mm.Artwork)
.Include(i => i.MediaVersions)
@@ -112,7 +114,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return await maybeExisting.Match(
plexMovie =>
Right<BaseError, MediaItemScanResult<PlexMovie>>(
new MediaItemScanResult<PlexMovie>(plexMovie) { IsAdded = true }).AsTask(),
new MediaItemScanResult<PlexMovie>(plexMovie) { IsAdded = false }).AsTask(),
async () => await AddPlexMovie(context, library, item));
}
@@ -192,6 +192,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.ThenInclude(s => s.Show)
.ThenInclude(s => s.ShowMetadata)
.ThenInclude(sm => sm.Actors)
.ThenInclude(a => a.Artwork)
.OrderBy(em => em.Episode.EpisodeNumber)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
@@ -293,6 +294,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.ThenInclude(em => em.Artwork)
.Include(i => i.EpisodeMetadata)
.ThenInclude(em => em.Actors)
.ThenInclude(a => a.Artwork)
.Include(i => i.MediaVersions)
.ThenInclude(mv => mv.MediaFiles)
.Include(i => i.MediaVersions)
@@ -393,6 +395,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.ThenInclude(sm => sm.Studios)
.Include(i => i.ShowMetadata)
.ThenInclude(sm => sm.Actors)
.ThenInclude(a => a.Artwork)
.Include(i => i.ShowMetadata)
.ThenInclude(sm => sm.Artwork)
.Include(i => i.LibraryPath)
@@ -402,7 +405,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
return await maybeExisting.Match(
plexShow => Right<BaseError, MediaItemScanResult<PlexShow>>(
new MediaItemScanResult<PlexShow>(plexShow) { IsAdded = true }).AsTask(),
new MediaItemScanResult<PlexShow>(plexShow) { IsAdded = false }).AsTask(),
async () => await AddPlexShow(dbContext, library, item));
}
@@ -434,6 +437,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.ThenInclude(mv => mv.Streams)
.Include(e => e.EpisodeMetadata)
.ThenInclude(em => em.Actors)
.ThenInclude(a => a.Artwork)
.OrderBy(i => i.Key)
.SingleOrDefaultAsync(i => i.Key == item.Key);
@@ -32,6 +32,7 @@ namespace ErsatzTV.Infrastructure.Plex
await service.GetLibraries(token.AuthToken).Map(r => r.MediaContainer.Directory);
return directory
// .Filter(l => l.Hidden == 0)
.Filter(l => l.Type.ToLowerInvariant() is "movie" or "show")
.Map(Project)
.Somes()
.ToList();
@@ -36,6 +36,7 @@ namespace ErsatzTV.Infrastructure.Search
private const string TagField = "tag";
private const string PlotField = "plot";
private const string LibraryNameField = "library_name";
private const string LibraryIdField = "library_id";
private const string TitleAndYearField = "title_and_year";
private const string JumpLetterField = "jump_letter";
private const string ReleaseDateField = "release_date";
@@ -62,7 +63,7 @@ namespace ErsatzTV.Infrastructure.Search
_cultureInfos = CultureInfo.GetCultures(CultureTypes.NeutralCultures).ToList();
}
public int Version => 7;
public int Version => 9;
public Task<bool> Initialize(ILocalFileSystem localFileSystem)
{
@@ -252,6 +253,7 @@ namespace ErsatzTV.Infrastructure.Search
new TextField(TitleField, metadata.Title, Field.Store.NO),
new StringField(SortTitleField, metadata.SortTitle.ToLowerInvariant(), Field.Store.NO),
new TextField(LibraryNameField, movie.LibraryPath.Library.Name, Field.Store.NO),
new StringField(LibraryIdField, movie.LibraryPath.Library.Id.ToString(), Field.Store.NO),
new StringField(TitleAndYearField, GetTitleAndYear(metadata), Field.Store.NO),
new StringField(JumpLetterField, GetJumpLetter(metadata), Field.Store.YES)
};
@@ -339,6 +341,7 @@ namespace ErsatzTV.Infrastructure.Search
new TextField(TitleField, metadata.Title, Field.Store.NO),
new StringField(SortTitleField, metadata.SortTitle.ToLowerInvariant(), Field.Store.NO),
new TextField(LibraryNameField, show.LibraryPath.Library.Name, Field.Store.NO),
new StringField(LibraryIdField, show.LibraryPath.Library.Id.ToString(), Field.Store.NO),
new StringField(TitleAndYearField, GetTitleAndYear(metadata), Field.Store.NO),
new StringField(JumpLetterField, GetJumpLetter(metadata), Field.Store.YES)
};
@@ -419,6 +422,7 @@ namespace ErsatzTV.Infrastructure.Search
new TextField(TitleField, metadata.Title, Field.Store.NO),
new StringField(SortTitleField, metadata.SortTitle.ToLowerInvariant(), Field.Store.NO),
new TextField(LibraryNameField, artist.LibraryPath.Library.Name, Field.Store.NO),
new StringField(LibraryIdField, artist.LibraryPath.Library.Id.ToString(), Field.Store.NO),
new StringField(TitleAndYearField, GetTitleAndYear(metadata), Field.Store.NO),
new StringField(JumpLetterField, GetJumpLetter(metadata), Field.Store.YES)
};
@@ -480,6 +484,7 @@ namespace ErsatzTV.Infrastructure.Search
new TextField(TitleField, metadata.Title, Field.Store.NO),
new StringField(SortTitleField, metadata.SortTitle.ToLowerInvariant(), Field.Store.NO),
new TextField(LibraryNameField, musicVideo.LibraryPath.Library.Name, Field.Store.NO),
new StringField(LibraryIdField, musicVideo.LibraryPath.Library.Id.ToString(), Field.Store.NO),
new StringField(TitleAndYearField, GetTitleAndYear(metadata), Field.Store.NO),
new StringField(JumpLetterField, GetJumpLetter(metadata), Field.Store.YES)
};
@@ -543,7 +548,7 @@ namespace ErsatzTV.Infrastructure.Search
}
private static string GetTitleAndYear(Metadata metadata) =>
$"{metadata.Title}_{metadata.Year}";
$"{metadata.Title}_{metadata.Year}".ToLowerInvariant();
private static string GetJumpLetter(Metadata metadata)
{
+6 -1
View File
@@ -22,7 +22,7 @@
<col/>
<col/>
<col/>
<col style="width: 180px;"/>
<col style="width: 240px;"/>
</ColGroup>
<HeaderContent>
<MudTh>Library Kind</MudTh>
@@ -60,6 +60,11 @@
</MudIconButton>
</MudTooltip>
}
<MudTooltip Text="Search Library">
<MudIconButton Icon="@Icons.Material.Filled.Search"
Link="@($"/search?query=library_id%3a{context.Id}")">
</MudIconButton>
</MudTooltip>
@if (context is LocalLibraryViewModel)
{
<MudTooltip Text="Edit Library">
+48 -11
View File
@@ -6,21 +6,58 @@ Movies, Shows, Artists and Music Videos can be searched using the search box nex
## Search Fields
The following fields are available for searching:
The `title` field of all media types is searched by default if no other field is specified.
- `title`: The movie, show, artist or music video name/title
- `genre`: The movie, show, or artist genre
- `tag`: The movie or show tag (not available with Plex metadata)
### Movies
The following fields are available for searching movies:
- `title`: The movie title
- `genre`: The movie genre
- `tag`: The movie tag (not available with Plex metadata)
- `plot`: The movie plot
- `studio`: The movie studio
- `actor`: An actor from the movie
- `library_name`: The name of the library that contains the movie
- `language`: The movie audio stream language
- `release_date`: The movie release date (YYYYMMDD)
- `type`: Always `movie`
### Shows
The following fields are available for searching shows:
- `title`: The show title
- `genre`: The show genre
- `tag`: The show tag (not available with Plex metadata)
- `plot`: The show plot
- `studio`: The show studio
- `actor`: An actor from the show
- `library_name`: The name of the library that contains the show
- `language`: The show audio stream language
- `release_date`: The show release date (YYYYMMDD)
- `type`: Always `show`
### Artists
The following fields are available for searching artists:
- `title`: The artist name
- `genre`: The artist genre
- `style`: The artist style
- `mood`: The artist mood
- `plot`: The movie or show plot
- `studio`: The movie or show studio
- `library_name`: The name of the library
- `language`: The movie, show or music video audio stream language
- `release_date`: The movie or show release date (YYYYMMDD)
- `type`: The media item type: `movie`, `show`, `artist` or `music_video`
- `library_name`: The name of the library that contains the artist
- `type`: Always `artist`
Note that the `title` field is searched by default if no other field is specified.
### Music Videos
The following fields are available for searching music videos:
- `title`: The music video title
- `genre`: The music video genre
- `library_name`: The name of the library that contains the music video
- `language`: The music video audio stream language
- `type`: Always `music_video`
## Sample Searches