@ -5,20 +5,16 @@ using System.Collections.Immutable;
using System.Globalization ;
using System.Linq ;
using System.Linq.Expressions ;
using System.Security.Cryptography.X509Certificates ;
using System.Text ;
using System.Threading ;
using System.Threading.Channels ;
using Jellyfin.Data.Enums ;
using Jellyfin.Extensions ;
using MediaBrowser.Controller ;
using MediaBrowser.Controller.Entities ;
using MediaBrowser.Controller.Entities.Audio ;
using MediaBrowser.Controller.Entities.Movies ;
using MediaBrowser.Controller.Entities.TV ;
using MediaBrowser.Controller.LiveTv ;
using MediaBrowser.Controller.Persistence ;
using MediaBrowser.Controller.Playlists ;
using MediaBrowser.Model.Dto ;
using MediaBrowser.Model.Entities ;
using MediaBrowser.Model.LiveTv ;
@ -26,6 +22,7 @@ using MediaBrowser.Model.Querying;
using Microsoft.EntityFrameworkCore ;
using BaseItemDto = MediaBrowser . Controller . Entities . BaseItem ;
using BaseItemEntity = Jellyfin . Data . Entities . BaseItemEntity ;
#pragma warning disable RS0030 // Do not use banned APIs
namespace Jellyfin.Server.Implementations.Item ;
@ -66,12 +63,12 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
using var context = dbProvider . CreateDbContext ( ) ;
using var transaction = context . Database . BeginTransaction ( ) ;
context . Peoples . Where ( e = > e . ItemId . Equals ( id ) ) . ExecuteDelete ( ) ;
context . Chapters . Where ( e = > e . ItemId . Equals ( id ) ) . ExecuteDelete ( ) ;
context . MediaStreamInfos . Where ( e = > e . ItemId . Equals ( id ) ) . ExecuteDelete ( ) ;
context . AncestorIds . Where ( e = > e . ItemId . Equals ( id ) ) . ExecuteDelete ( ) ;
context . ItemValues . Where ( e = > e . ItemId . Equals ( id ) ) . ExecuteDelete ( ) ;
context . BaseItems . Where ( e = > e . Id . Equals ( id ) ) . ExecuteDelete ( ) ;
context . Peoples . Where ( e = > e . ItemId = = id ) . ExecuteDelete ( ) ;
context . Chapters . Where ( e = > e . ItemId = = id ) . ExecuteDelete ( ) ;
context . MediaStreamInfos . Where ( e = > e . ItemId = = id ) . ExecuteDelete ( ) ;
context . AncestorIds . Where ( e = > e . ItemId = = id ) . ExecuteDelete ( ) ;
context . ItemValues . Where ( e = > e . ItemId = = id ) . ExecuteDelete ( ) ;
context . BaseItems . Where ( e = > e . Id = = id ) . ExecuteDelete ( ) ;
context . SaveChanges ( ) ;
transaction . Commit ( ) ;
}
@ -113,8 +110,8 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
PrepareFilterQuery ( filter ) ;
using var context = dbProvider . CreateDbContext ( ) ;
var dbQuery = TranslateQuery ( context . BaseItems . AsNoTracking ( ) , context , filter )
. DistinctBy ( e = > e . Id ) ;
var dbQuery = TranslateQuery ( context . BaseItems . AsNoTracking ( ) , context , filter ) ;
// .DistinctBy(e => e.Id) ;
var enableGroupByPresentationUniqueKey = EnableGroupByPresentationUniqueKey ( filter ) ;
if ( enableGroupByPresentationUniqueKey & & filter . GroupBySeriesPresentationUniqueKey )
@ -266,8 +263,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
PrepareFilterQuery ( filter ) ;
using var context = dbProvider . CreateDbContext ( ) ;
var dbQuery = TranslateQuery ( context . BaseItems , context , filter )
. DistinctBy ( e = > e . Id ) ;
var dbQuery = TranslateQuery ( context . BaseItems , context , filter ) ;
if ( filter . Limit . HasValue | | filter . StartIndex . HasValue )
{
var offset = filter . StartIndex ? ? 0 ;
@ -299,6 +295,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
return dbQuery . Count ( ) ;
}
#pragma warning disable CA1307 // Specify StringComparison for clarity
private IQueryable < BaseItemEntity > TranslateQuery (
IQueryable < BaseItemEntity > baseQuery ,
JellyfinDbContext context ,
@ -419,7 +416,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( ! string . IsNullOrEmpty ( filter . SearchTerm ) )
{
baseQuery = baseQuery . Where ( e = > e . CleanName ! . Contains ( filter . SearchTerm , StringComparison . InvariantCultureIgnoreCase ) | | ( e . OriginalTitle ! = null & & e . OriginalTitle . Contains ( filter . SearchTerm , StringComparison . InvariantCultureIgnoreCase ) ) ) ;
baseQuery = baseQuery . Where ( e = > e . CleanName ! . Contains ( filter . SearchTerm ) | | ( e . OriginalTitle ! = null & & e . OriginalTitle . Contains ( filter . SearchTerm ) ) ) ;
}
if ( filter . IsFolder . HasValue )
@ -474,18 +471,15 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
baseQuery = baseQuery . Where ( e = > includeTypeName . Contains ( e . Type ) ) ;
}
if ( filter . ChannelIds . Count == 1 )
if ( filter . ChannelIds . Count > 0 )
{
baseQuery = baseQuery . Where ( e = > e . ChannelId = = filter . ChannelIds [ 0 ] . ToString ( "N" , CultureInfo . InvariantCulture ) ) ;
}
else if ( filter . ChannelIds . Count > 1 )
{
baseQuery = baseQuery . Where ( e = > filter . ChannelIds . Select ( f = > f . ToString ( "N" , CultureInfo . InvariantCulture ) ) . Contains ( e . ChannelId ) ) ;
var channelIds = filter . ChannelIds . Select ( e = > e . ToString ( "N" , CultureInfo . InvariantCulture ) ) . ToArray ( ) ;
baseQuery = baseQuery . Where ( e = > channelIds . Contains ( e . ChannelId ) ) ;
}
if ( ! filter . ParentId . IsEmpty ( ) )
{
baseQuery = baseQuery . Where ( e = > e . ParentId .Equals ( filter . ParentId ) ) ;
baseQuery = baseQuery . Where ( e = > e . ParentId !. Value = = filter . ParentId ) ;
}
if ( ! string . IsNullOrWhiteSpace ( filter . Path ) )
@ -591,7 +585,8 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . TrailerTypes . Length > 0 )
{
baseQuery = baseQuery . Where ( e = > filter . TrailerTypes . Any ( f = > e . TrailerTypes ! . Contains ( f . ToString ( ) , StringComparison . OrdinalIgnoreCase ) ) ) ;
var trailerTypes = filter . TrailerTypes . Select ( e = > e . ToString ( ) ) . ToArray ( ) ;
baseQuery = baseQuery . Where ( e = > trailerTypes . Any ( f = > e . TrailerTypes ! . Contains ( f ) ) ) ;
}
if ( filter . IsAiring . HasValue )
@ -611,7 +606,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
baseQuery = baseQuery
. Where ( e = >
context . Peoples . Where ( w = > context . BaseItems . Where ( w = > filter . PersonIds . Contains ( w . Id ) ) . Any ( f = > f . Name = = w . Name ) )
. Any ( f = > f . ItemId . Equals ( e . Id ) ) ) ;
. Any ( f = > f . ItemId = = e . Id ) ) ;
}
if ( ! string . IsNullOrWhiteSpace ( filter . Person ) )
@ -649,12 +644,12 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
{
baseQuery = baseQuery . Where ( e = >
e . CleanName = = filter . NameContains
| | e . OriginalTitle ! . Contains ( filter . NameContains ! , StringComparison . Ordinal )) ;
| | e . OriginalTitle ! . Contains ( filter . NameContains ! )) ;
}
if ( ! string . IsNullOrWhiteSpace ( filter . NameStartsWith ) )
{
baseQuery = baseQuery . Where ( e = > e . SortName ! . Contains ( filter . NameStartsWith , StringComparison . OrdinalIgnoreCase )) ;
baseQuery = baseQuery . Where ( e = > e . SortName ! . Contains ( filter . NameStartsWith )) ;
}
if ( ! string . IsNullOrWhiteSpace ( filter . NameStartsWithOrGreater ) )
@ -671,31 +666,32 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . ImageTypes . Length > 0 )
{
baseQuery = baseQuery . Where ( e = > filter . ImageTypes . Any ( f = > e . Images ! . Contains ( f . ToString ( ) , StringComparison . InvariantCulture ) ) ) ;
var imgTypes = filter . ImageTypes . Select ( e = > e . ToString ( ) ) . ToArray ( ) ;
baseQuery = baseQuery . Where ( e = > imgTypes . Any ( f = > e . Images ! . Contains ( f ) ) ) ;
}
if ( filter . IsLiked . HasValue )
{
baseQuery = baseQuery
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( filter . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . Rating > = UserItemData . MinLikeValue ) ;
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = filter . User ! . Id & & f . Key = = e . UserDataKey ) ! . Rating > = UserItemData . MinLikeValue ) ;
}
if ( filter . IsFavoriteOrLiked . HasValue )
{
baseQuery = baseQuery
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( filter . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . IsFavorite = = filter . IsFavoriteOrLiked ) ;
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = filter . User ! . Id & & f . Key = = e . UserDataKey ) ! . IsFavorite = = filter . IsFavoriteOrLiked ) ;
}
if ( filter . IsFavorite . HasValue )
{
baseQuery = baseQuery
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( filter . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . IsFavorite = = filter . IsFavorite ) ;
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = filter . User ! . Id & & f . Key = = e . UserDataKey ) ! . IsFavorite = = filter . IsFavorite ) ;
}
if ( filter . IsPlayed . HasValue )
{
baseQuery = baseQuery
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( filter . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . Played = = filter . IsPlayed . Value ) ;
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = filter . User ! . Id & & f . Key = = e . UserDataKey ) ! . Played = = filter . IsPlayed . Value ) ;
}
if ( filter . IsResumable . HasValue )
@ -703,12 +699,12 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . IsResumable . Value )
{
baseQuery = baseQuery
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( filter . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . PlaybackPositionTicks > 0 ) ;
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = filter . User ! . Id & & f . Key = = e . UserDataKey ) ! . PlaybackPositionTicks > 0 ) ;
}
else
{
baseQuery = baseQuery
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( filter . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . PlaybackPositionTicks = = 0 ) ;
. Where ( e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = filter . User ! . Id & & f . Key = = e . UserDataKey ) ! . PlaybackPositionTicks = = 0 ) ;
}
}
@ -925,7 +921,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . HasDeadParentId . HasValue & & filter . HasDeadParentId . Value )
{
baseQuery = baseQuery
. Where ( e = > e . ParentId . HasValue & & context . BaseItems . Any ( f = > f . Id . Equals ( e . ParentId . Value ) ) ) ;
. Where ( e = > e . ParentId . HasValue & & context . BaseItems . Any ( f = > f . Id = = e . ParentId . Value ) ) ;
}
if ( filter . IsDeadArtist . HasValue & & filter . IsDeadArtist . Value )
@ -1048,11 +1044,11 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
var enableItemsByName = ( filter . IncludeItemsByName ? ? false ) & & includedItemByNameTypes . Count > 0 ;
if ( enableItemsByName & & includedItemByNameTypes . Count > 0 )
{
baseQuery = baseQuery . Where ( e = > includedItemByNameTypes . Contains ( e . Type ) | | queryTopParentIds . Any ( w = > w . Equals ( e . TopParentId ! . Value ) ) ) ;
baseQuery = baseQuery . Where ( e = > includedItemByNameTypes . Contains ( e . Type ) | | queryTopParentIds . Any ( w = > w = = e . TopParentId ! . Value ) ) ;
}
else
{
baseQuery = baseQuery . Where ( e = > queryTopParentIds . Any ( w = > w . Equals ( e . TopParentId ! . Value ) ) ) ;
baseQuery = baseQuery . Where ( e = > queryTopParentIds . Any ( w = > w = = e . TopParentId ! . Value ) ) ;
}
}
@ -1064,7 +1060,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( ! string . IsNullOrWhiteSpace ( filter . AncestorWithPresentationUniqueKey ) )
{
baseQuery = baseQuery
. Where ( e = > context . BaseItems . Where ( f = > f . PresentationUniqueKey = = filter . AncestorWithPresentationUniqueKey ) . Any ( f = > f . AncestorIds ! . Any ( w = > w . ItemId . Equals ( f . Id ) ) ) ) ;
. Where ( e = > context . BaseItems . Where ( f = > f . PresentationUniqueKey = = filter . AncestorWithPresentationUniqueKey ) . Any ( f = > f . AncestorIds ! . Any ( w = > w . ItemId = = f . Id ) ) ) ;
}
if ( ! string . IsNullOrWhiteSpace ( filter . SeriesPresentationUniqueKey ) )
@ -1090,7 +1086,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
. Where ( e = > e . ItemValues ! . Where ( e = > e . Type = = 6 )
. Any ( f = > filter . IncludeInheritedTags . Contains ( f . CleanValue ) )
| |
( e . ParentId . HasValue & & context . ItemValues . Where ( w = > w . ItemId . Equals ( e . ParentId . Value ) ) ! . Where ( e = > e . Type = = 6 )
( e . ParentId . HasValue & & context . ItemValues . Where ( w = > w . ItemId = = e . ParentId . Value ) ! . Where ( e = > e . Type = = 6 )
. Any ( f = > filter . IncludeInheritedTags . Contains ( f . CleanValue ) ) ) ) ;
}
@ -1112,21 +1108,23 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . SeriesStatuses . Length > 0 )
{
var seriesStatus = filter . SeriesStatuses . Select ( e = > e . ToString ( ) ) . ToArray ( ) ;
baseQuery = baseQuery
. Where ( e = > filter. SeriesStatuse s. Any ( f = > e . Data ! . Contains ( f . ToString ( ) , StringComparison . InvariantCultureIgnoreCase ) ) ) ;
. Where ( e = > seriesStatu s. Any ( f = > e . Data ! . Contains ( f ) ) ) ;
}
if ( filter . BoxSetLibraryFolders . Length > 0 )
{
var boxsetFolders = filter . BoxSetLibraryFolders . Select ( e = > e . ToString ( "N" , CultureInfo . InvariantCulture ) ) . ToArray ( ) ;
baseQuery = baseQuery
. Where ( e = > filter. BoxSetLibrary Folders. Any ( f = > e . Data ! . Contains ( f . ToString ( "N" , CultureInfo . InvariantCulture ) , StringComparison . InvariantCultureIgnoreCase ) ) ) ;
. Where ( e = > boxset Folders. Any ( f = > e . Data ! . Contains ( f ) ) ) ;
}
if ( filter . VideoTypes . Length > 0 )
{
var videoTypeBs = filter . VideoTypes . Select ( e = > $"\" VideoType \ ":\"" + e + "\"" ) ;
baseQuery = baseQuery
. Where ( e = > videoTypeBs . Any ( f = > e . Data ! . Contains ( f , StringComparison . InvariantCultureIgnoreCase )) ) ;
. Where ( e = > videoTypeBs . Any ( f = > e . Data ! . Contains ( f )) ) ;
}
if ( filter . Is3D . HasValue )
@ -1134,12 +1132,12 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . Is3D . Value )
{
baseQuery = baseQuery
. Where ( e = > e . Data ! . Contains ( "Video3DFormat" , StringComparison . InvariantCultureIgnoreCase )) ;
. Where ( e = > e . Data ! . Contains ( "Video3DFormat" )) ;
}
else
{
baseQuery = baseQuery
. Where ( e = > ! e . Data ! . Contains ( "Video3DFormat" , StringComparison . InvariantCultureIgnoreCase )) ;
. Where ( e = > ! e . Data ! . Contains ( "Video3DFormat" )) ;
}
}
@ -1148,12 +1146,12 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
if ( filter . IsPlaceHolder . Value )
{
baseQuery = baseQuery
. Where ( e = > e . Data ! . Contains ( "IsPlaceHolder\":true" , StringComparison . InvariantCultureIgnoreCase )) ;
. Where ( e = > e . Data ! . Contains ( "IsPlaceHolder\":true" )) ;
}
else
{
baseQuery = baseQuery
. Where ( e = > ! e . Data ! . Contains ( "IsPlaceHolder\":true" , StringComparison . InvariantCultureIgnoreCase )) ;
. Where ( e = > ! e . Data ! . Contains ( "IsPlaceHolder\":true" )) ;
}
}
@ -1212,7 +1210,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
using var db = dbProvider . CreateDbContext ( ) ;
db . BaseItems
. Where ( e = > e . Id . Equals ( item . Id ) )
. Where ( e = > e . Id = = item . Id )
. ExecuteUpdate ( e = > e . SetProperty ( f = > f . Images , images ) ) ;
}
@ -1246,11 +1244,20 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
}
using var context = dbProvider . CreateDbContext ( ) ;
using var transaction = context . Database . BeginTransaction ( ) ;
foreach ( var item in tuples )
{
var entity = Map ( item . Item ) ;
context . BaseItems . Add ( entity ) ;
if ( ! context . BaseItems . Any ( e = > e . Id = = entity . Id ) )
{
context . BaseItems . Add ( entity ) ;
}
else
{
context . BaseItems . Attach ( entity ) . State = EntityState . Modified ;
}
context . AncestorIds . Where ( e = > e . ItemId = = entity . Id ) . ExecuteDelete ( ) ;
if ( item . Item . SupportsAncestors & & item . AncestorIds ! = null )
{
foreach ( var ancestorId in item . AncestorIds )
@ -1260,13 +1267,13 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
Item = entity ,
AncestorIdText = ancestorId . ToString ( ) ,
Id = ancestorId ,
ItemId = entity. Id
ItemId = Guid. Empty
} ) ;
}
}
var itemValues = GetItemValuesToSave ( item . Item , item . InheritedTags ) ;
context . ItemValues . Where ( e = > e . ItemId . Equals ( entity . Id ) ) . ExecuteDelete ( ) ;
context . ItemValues . Where ( e = > e . ItemId = = entity . Id ) . ExecuteDelete ( ) ;
foreach ( var itemValue in itemValues )
{
context . ItemValues . Add ( new ( )
@ -1275,12 +1282,13 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
Type = itemValue . MagicNumber ,
Value = itemValue . Value ,
CleanValue = GetCleanValue ( itemValue . Value ) ,
ItemId = entity. Id
ItemId = Guid. Empty
} ) ;
}
}
context . SaveChanges ( true ) ;
context . SaveChanges ( ) ;
transaction . Commit ( ) ;
}
/// <inheritdoc cref="IItemRepository" />
@ -1292,7 +1300,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
}
using var context = dbProvider . CreateDbContext ( ) ;
var item = context . BaseItems . FirstOrDefault ( e = > e . Id . Equals ( id ) ) ;
var item = context . BaseItems . FirstOrDefault ( e = > e . Id = = id ) ;
if ( item is null )
{
return null ;
@ -1380,7 +1388,7 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
dto . Audio = Enum . Parse < ProgramAudio > ( entity . Audio ) ;
}
dto . ExtraIds = entity . ExtraIds ?. Split ( '|' ) . Select ( e = > Guid . Parse ( e ) ) . ToArray ( ) ;
dto . ExtraIds = string . IsNullOrWhiteSpace ( entity . ExtraIds ) ? null : entity . ExtraIds . Split ( '|' ) . Select ( e = > Guid . Parse ( e ) ) . ToArray ( ) ;
dto . ProductionLocations = entity . ProductionLocations ? . Split ( '|' ) ;
dto . Studios = entity . Studios ? . Split ( '|' ) ;
dto . Tags = entity . Tags ? . Split ( '|' ) ;
@ -1535,8 +1543,8 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
entity . Audio = dto . Audio ? . ToString ( ) ;
entity . ExtraType = dto . ExtraType ? . ToString ( ) ;
entity . ExtraIds = string . Join ( '|' , dto . ExtraIds ) ;
entity . ProductionLocations = string . Join ( '|' , dto . ProductionLocations ) ;
entity . ExtraIds = dto . ExtraIds is not null ? string . Join ( '|' , dto . ExtraIds ) : null ;
entity . ProductionLocations = dto . ProductionLocations is not null ? string . Join ( '|' , dto . ProductionLocations ) : null ;
entity . Studios = dto . Studios is not null ? string . Join ( '|' , dto . Studios ) : null ;
entity . Tags = dto . Tags is not null ? string . Join ( '|' , dto . Tags ) : null ;
entity . LockedFields = dto . LockedFields is not null ? string . Join ( '|' , dto . LockedFields ) : null ;
@ -1628,15 +1636,15 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
. Where ( e = > itemValueTypes . Contains ( e . Type ) ) ;
if ( withItemTypes . Count > 0 )
{
query = query . Where ( e = > context . BaseItems . Where ( e = > withItemTypes . Contains ( e . Type ) ) . Any ( f = > f . ItemValues ! . Any ( w = > w . ItemId . Equals ( e . ItemId ) ) ) ) ;
query = query . Where ( e = > context . BaseItems . Where ( e = > withItemTypes . Contains ( e . Type ) ) . Any ( f = > f . ItemValues ! . Any ( w = > w . ItemId = = e . ItemId ) ) ) ;
}
if ( excludeItemTypes . Count > 0 )
{
query = query . Where ( e = > ! context . BaseItems . Where ( e = > withItemTypes . Contains ( e . Type ) ) . Any ( f = > f . ItemValues ! . Any ( w = > w . ItemId . Equals ( e . ItemId ) ) ) ) ;
query = query . Where ( e = > ! context . BaseItems . Where ( e = > withItemTypes . Contains ( e . Type ) ) . Any ( f = > f . ItemValues ! . Any ( w = > w . ItemId = = e . ItemId ) ) ) ;
}
query = query . DistinctBy ( e = > e . CleanValue ) ;
// query = query.DistinctBy(e => e.CleanValue) ;
return query . Select ( e = > e . CleanValue ) . ToImmutableArray ( ) ;
}
@ -2131,12 +2139,12 @@ public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbPr
ItemSortBy . AirTime = > e = > e . SortName , // TODO
ItemSortBy . Runtime = > e = > e . RunTimeTicks ,
ItemSortBy . Random = > e = > EF . Functions . Random ( ) ,
ItemSortBy . DatePlayed = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( query . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . LastPlayedDate ,
ItemSortBy . PlayCount = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( query . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . PlayCount ,
ItemSortBy . IsFavoriteOrLiked = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( query . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . IsFavorite ,
ItemSortBy . DatePlayed = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = query . User ! . Id & & f . Key = = e . UserDataKey ) ! . LastPlayedDate ,
ItemSortBy . PlayCount = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = query . User ! . Id & & f . Key = = e . UserDataKey ) ! . PlayCount ,
ItemSortBy . IsFavoriteOrLiked = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = query . User ! . Id & & f . Key = = e . UserDataKey ) ! . IsFavorite ,
ItemSortBy . IsFolder = > e = > e . IsFolder ,
ItemSortBy . IsPlayed = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( query . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . Played ,
ItemSortBy . IsUnplayed = > e = > ! e . UserData ! . FirstOrDefault ( f = > f . UserId . Equals ( query . User ! . Id ) & & f . Key = = e . UserDataKey ) ! . Played ,
ItemSortBy . IsPlayed = > e = > e . UserData ! . FirstOrDefault ( f = > f . UserId = = query . User ! . Id & & f . Key = = e . UserDataKey ) ! . Played ,
ItemSortBy . IsUnplayed = > e = > ! e . UserData ! . FirstOrDefault ( f = > f . UserId = = query . User ! . Id & & f . Key = = e . UserDataKey ) ! . Played ,
ItemSortBy . DateLastContentAdded = > e = > e . DateLastMediaAdded ,
ItemSortBy . Artist = > e = > e . ItemValues ! . Where ( f = > f . Type = = 0 ) . Select ( f = > f . CleanValue ) ,
ItemSortBy . AlbumArtist = > e = > e . ItemValues ! . Where ( f = > f . Type = = 1 ) . Select ( f = > f . CleanValue ) ,