mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 19:37:55 +02:00
commit
81c7999f61
14 changed files with 176 additions and 236 deletions
|
@ -439,6 +439,12 @@ namespace MediaBrowser.Api.LiveTv
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/LiveTv/ListingProviders/Default", "GET")]
|
||||
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||
public class GetDefaultListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/LiveTv/ListingProviders", "POST", Summary = "Adds a listing provider")]
|
||||
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||
public class AddListingProvider : ListingsProviderInfo, IReturn<ListingsProviderInfo>
|
||||
|
@ -525,6 +531,11 @@ namespace MediaBrowser.Api.LiveTv
|
|||
_dtoService = dtoService;
|
||||
}
|
||||
|
||||
public object Get(GetDefaultListingProvider request)
|
||||
{
|
||||
return ToOptimizedResult(new ListingsProviderInfo());
|
||||
}
|
||||
|
||||
public async Task<object> Get(GetSatChannnelScanResult request)
|
||||
{
|
||||
var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false);
|
||||
|
|
|
@ -164,49 +164,15 @@ namespace MediaBrowser.Controller.Entities
|
|||
item.DateModified = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
AddChildInternal(item.Id);
|
||||
|
||||
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected void AddChildrenInternal(List<Guid> children)
|
||||
{
|
||||
lock (_childrenSyncLock)
|
||||
{
|
||||
var newChildren = ChildIds.ToList();
|
||||
newChildren.AddRange(children);
|
||||
_children = newChildren.ToList();
|
||||
}
|
||||
}
|
||||
protected void AddChildInternal(Guid child)
|
||||
{
|
||||
lock (_childrenSyncLock)
|
||||
{
|
||||
var childIds = ChildIds.ToList();
|
||||
if (!childIds.Contains(child))
|
||||
{
|
||||
childIds.Add(child);
|
||||
_children = childIds.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void RemoveChildrenInternal(List<Guid> children)
|
||||
{
|
||||
lock (_childrenSyncLock)
|
||||
{
|
||||
_children = ChildIds.Except(children).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the child.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
public void RemoveChild(BaseItem item)
|
||||
{
|
||||
RemoveChildrenInternal(new[] { item.Id }.ToList());
|
||||
|
||||
item.SetParent(null);
|
||||
}
|
||||
|
||||
|
@ -241,33 +207,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The children
|
||||
/// </summary>
|
||||
private IReadOnlyList<Guid> _children;
|
||||
/// <summary>
|
||||
/// The _children sync lock
|
||||
/// </summary>
|
||||
private readonly object _childrenSyncLock = new object();
|
||||
/// <summary>
|
||||
/// Gets or sets the actual children.
|
||||
/// </summary>
|
||||
/// <value>The actual children.</value>
|
||||
protected virtual IEnumerable<Guid> ChildIds
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_childrenSyncLock)
|
||||
{
|
||||
if (_children == null)
|
||||
{
|
||||
_children = LoadChildren().ToList();
|
||||
}
|
||||
return _children.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the actual children.
|
||||
/// </summary>
|
||||
|
@ -277,7 +216,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
get
|
||||
{
|
||||
return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
|
||||
return LoadChildren().Select(LibraryManager.GetItemById).Where(i => i != null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,8 +418,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
if (actualRemovals.Count > 0)
|
||||
{
|
||||
RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
|
||||
|
||||
foreach (var item in actualRemovals)
|
||||
{
|
||||
Logger.Debug("Removed item: " + item.Path);
|
||||
|
@ -493,8 +430,6 @@ namespace MediaBrowser.Controller.Entities
|
|||
}
|
||||
|
||||
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
AddChildrenInternal(newItems.Select(i => i.Id).ToList());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -766,7 +701,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
{
|
||||
if (!(this is ICollectionFolder))
|
||||
{
|
||||
Logger.Debug("Query requires post-filtering due to LinkedChildren");
|
||||
Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,13 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
var series = Series;
|
||||
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
||||
{
|
||||
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
||||
var seriesUserDataKeys = series.GetUserDataKeys();
|
||||
var take = seriesUserDataKeys.Count;
|
||||
if (seriesUserDataKeys.Count > 1)
|
||||
{
|
||||
take--;
|
||||
}
|
||||
list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
|
|
@ -196,52 +196,17 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
{
|
||||
var config = user.Configuration;
|
||||
|
||||
return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||
return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||
}
|
||||
|
||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||
{
|
||||
var series = Series;
|
||||
|
||||
if (IndexNumber.HasValue && series != null)
|
||||
{
|
||||
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
||||
return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null);
|
||||
}
|
||||
|
||||
var episodes = GetRecursiveChildren(user)
|
||||
.OfType<Episode>();
|
||||
|
||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||
public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
|
||||
{
|
||||
var seasonNumber = IndexNumber;
|
||||
var list = episodes.ToList();
|
||||
|
||||
if (seasonNumber.HasValue)
|
||||
{
|
||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
||||
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
||||
.Where(i => !i.ParentIndexNumber.HasValue));
|
||||
}
|
||||
|
||||
episodes = list.DistinctBy(i => i.Id);
|
||||
}
|
||||
|
||||
if (!includeMissingEpisodes)
|
||||
{
|
||||
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
||||
}
|
||||
if (!includeVirtualUnairedEpisodes)
|
||||
{
|
||||
episodes = episodes.Where(i => !i.IsVirtualUnaired);
|
||||
}
|
||||
|
||||
return LibraryManager
|
||||
.Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
|
||||
.Cast<Episode>();
|
||||
return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes);
|
||||
}
|
||||
|
||||
public IEnumerable<Episode> GetEpisodes()
|
||||
|
|
|
@ -183,24 +183,20 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
|
||||
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
||||
{
|
||||
if (query.User == null)
|
||||
{
|
||||
return base.GetItemsInternal(query);
|
||||
}
|
||||
|
||||
var user = query.User;
|
||||
|
||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||
|
||||
IEnumerable<BaseItem> items;
|
||||
|
||||
if (query.User == null)
|
||||
{
|
||||
items = query.Recursive
|
||||
? GetRecursiveChildren(filter)
|
||||
: Children.Where(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
items = query.Recursive
|
||||
? GetSeasons(user).Cast<BaseItem>().Concat(GetEpisodes(user)).Where(filter)
|
||||
: GetSeasons(user).Where(filter);
|
||||
}
|
||||
|
||||
var result = PostFilterAndSort(items, query);
|
||||
|
||||
|
@ -260,8 +256,10 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
|
||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
|
||||
{
|
||||
var allSeriesEpisodes = GetAllEpisodes(user).ToList();
|
||||
|
||||
var allEpisodes = GetSeasons(user, true, true)
|
||||
.SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired))
|
||||
.SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes))
|
||||
.Reverse()
|
||||
.ToList();
|
||||
|
||||
|
@ -350,7 +348,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
return false;
|
||||
}
|
||||
|
||||
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||
private IEnumerable<Episode> GetAllEpisodes(User user)
|
||||
{
|
||||
IEnumerable<Episode> episodes;
|
||||
|
||||
|
@ -388,7 +386,24 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}).Cast<Episode>();
|
||||
}
|
||||
|
||||
episodes = FilterEpisodesBySeason(episodes, parentSeason, DisplaySpecialsWithSeasons);
|
||||
return episodes;
|
||||
}
|
||||
|
||||
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||
{
|
||||
IEnumerable<Episode> episodes = GetAllEpisodes(user);
|
||||
|
||||
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
|
||||
}
|
||||
|
||||
public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
|
||||
{
|
||||
if (allSeriesEpisodes == null)
|
||||
{
|
||||
return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
||||
}
|
||||
|
||||
var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, DisplaySpecialsWithSeasons);
|
||||
|
||||
if (!includeMissingEpisodes)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Persistence
|
|||
/// <returns>Task{UserItemData}.</returns>
|
||||
UserItemData GetUserData(Guid userId, string key);
|
||||
|
||||
UserItemData GetUserData(Guid userId, List<string> keys);
|
||||
|
||||
/// <summary>
|
||||
/// Return all user data associated with the given user
|
||||
/// </summary>
|
||||
|
|
|
@ -73,9 +73,15 @@ namespace MediaBrowser.Model.LiveTv
|
|||
|
||||
public string[] EnabledTuners { get; set; }
|
||||
public bool EnableAllTuners { get; set; }
|
||||
public string[] NewsGenres { get; set; }
|
||||
public string[] SportsGenres { get; set; }
|
||||
public string[] KidsGenres { get; set; }
|
||||
|
||||
public ListingsProviderInfo()
|
||||
{
|
||||
NewsGenres = new string[] { "news" };
|
||||
SportsGenres = new string[] { "sports", "basketball", "baseball", "football" };
|
||||
KidsGenres = new string[] { "kids", "family", "children" };
|
||||
EnabledTuners = new string[] { };
|
||||
EnableAllTuners = true;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@ using MediaBrowser.Model.Entities;
|
|||
using MediaBrowser.Model.Serialization;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -47,7 +49,16 @@ namespace MediaBrowser.Providers.Omdb
|
|||
|
||||
}).ConfigureAwait(false))
|
||||
{
|
||||
var result = _jsonSerializer.DeserializeFromStream<RootObject>(stream);
|
||||
string resultString;
|
||||
|
||||
using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
|
||||
{
|
||||
resultString = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
resultString = resultString.Replace("\"N/A\"", "\"\"");
|
||||
|
||||
var result = _jsonSerializer.DeserializeFromString<RootObject>(resultString);
|
||||
|
||||
// Only take the name and rating if the user's language is set to english, since Omdb has no localization
|
||||
if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
|
||||
|
@ -84,7 +95,6 @@ namespace MediaBrowser.Providers.Omdb
|
|||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(result.tomatoConsensus)
|
||||
&& !string.Equals(result.tomatoConsensus, "n/a", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.Equals(result.tomatoConsensus, "No consensus yet.", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
hasCriticRating.CriticRatingSummary = WebUtility.HtmlDecode(result.tomatoConsensus);
|
||||
|
@ -109,14 +119,12 @@ namespace MediaBrowser.Providers.Omdb
|
|||
item.CommunityRating = imdbRating;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(result.Website)
|
||||
&& !string.Equals(result.Website, "n/a", StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.IsNullOrEmpty(result.Website))
|
||||
{
|
||||
item.HomePageUrl = result.Website;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(result.imdbID)
|
||||
&& !string.Equals(result.imdbID, "n/a", StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.IsNullOrWhiteSpace(result.imdbID))
|
||||
{
|
||||
item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
|
||||
}
|
||||
|
@ -130,8 +138,7 @@ namespace MediaBrowser.Providers.Omdb
|
|||
// Grab series genres because imdb data is better than tvdb. Leave movies alone
|
||||
// But only do it if english is the preferred language because this data will not be localized
|
||||
if (ShouldFetchGenres(item) &&
|
||||
!string.IsNullOrWhiteSpace(result.Genre) &&
|
||||
!string.Equals(result.Genre, "n/a", StringComparison.OrdinalIgnoreCase))
|
||||
!string.IsNullOrWhiteSpace(result.Genre))
|
||||
{
|
||||
item.Genres.Clear();
|
||||
|
||||
|
@ -156,8 +163,7 @@ namespace MediaBrowser.Providers.Omdb
|
|||
}
|
||||
|
||||
var hasAwards = item as IHasAwards;
|
||||
if (hasAwards != null && !string.IsNullOrEmpty(result.Awards) &&
|
||||
!string.Equals(result.Awards, "n/a", StringComparison.OrdinalIgnoreCase))
|
||||
if (hasAwards != null && !string.IsNullOrEmpty(result.Awards))
|
||||
{
|
||||
hasAwards.AwardSummary = WebUtility.HtmlDecode(result.Awards);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
public event EventHandler<UserDataSaveEventArgs> UserDataSaved;
|
||||
|
||||
private readonly Dictionary<string, UserItemData> _userData = new Dictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, UserItemData> _userData =
|
||||
new ConcurrentDictionary<string, UserItemData>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
|
@ -64,13 +65,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
try
|
||||
{
|
||||
await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var newValue = userData;
|
||||
|
||||
lock (_userData)
|
||||
{
|
||||
_userData[GetCacheKey(userId, key)] = newValue;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -80,6 +74,9 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
}
|
||||
}
|
||||
|
||||
var cacheKey = GetCacheKey(userId, item.Id);
|
||||
_userData.AddOrUpdate(cacheKey, userData, (k, v) => userData);
|
||||
|
||||
EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs
|
||||
{
|
||||
Keys = keys,
|
||||
|
@ -140,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return Repository.GetAllUserData(userId);
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(Guid userId, List<string> keys)
|
||||
public UserItemData GetUserData(Guid userId, Guid itemId, List<string> keys)
|
||||
{
|
||||
if (userId == Guid.Empty)
|
||||
{
|
||||
|
@ -150,26 +147,23 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
throw new ArgumentNullException("keys");
|
||||
}
|
||||
|
||||
lock (_userData)
|
||||
if (keys.Count == 0)
|
||||
{
|
||||
foreach (var key in keys)
|
||||
{
|
||||
var cacheKey = GetCacheKey(userId, key);
|
||||
UserItemData value;
|
||||
if (_userData.TryGetValue(cacheKey, out value))
|
||||
{
|
||||
return value;
|
||||
throw new ArgumentException("UserData keys cannot be empty.");
|
||||
}
|
||||
|
||||
value = Repository.GetUserData(userId, key);
|
||||
var cacheKey = GetCacheKey(userId, itemId);
|
||||
|
||||
if (value != null)
|
||||
return _userData.GetOrAdd(cacheKey, k => GetUserDataInternal(userId, keys));
|
||||
}
|
||||
|
||||
private UserItemData GetUserDataInternal(Guid userId, List<string> keys)
|
||||
{
|
||||
_userData[cacheKey] = value;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
var userData = Repository.GetUserData(userId, keys);
|
||||
|
||||
if (userData != null)
|
||||
{
|
||||
return userData;
|
||||
}
|
||||
|
||||
if (keys.Count > 0)
|
||||
|
@ -184,57 +178,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user data.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>Task{UserItemData}.</returns>
|
||||
public UserItemData GetUserData(Guid userId, string key)
|
||||
{
|
||||
if (userId == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentNullException("userId");
|
||||
}
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
lock (_userData)
|
||||
{
|
||||
var cacheKey = GetCacheKey(userId, key);
|
||||
UserItemData value;
|
||||
if (_userData.TryGetValue(cacheKey, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
value = Repository.GetUserData(userId, key);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
value = new UserItemData
|
||||
{
|
||||
UserId = userId,
|
||||
Key = key
|
||||
};
|
||||
}
|
||||
|
||||
_userData[cacheKey] = value;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal key.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
private string GetCacheKey(Guid userId, string key)
|
||||
private string GetCacheKey(Guid userId, Guid itemId)
|
||||
{
|
||||
return userId + key;
|
||||
return userId.ToString("N") + itemId.ToString("N");
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(IHasUserData user, IHasUserData item)
|
||||
|
@ -249,7 +199,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
public UserItemData GetUserData(Guid userId, IHasUserData item)
|
||||
{
|
||||
return GetUserData(userId, item.GetUserDataKeys());
|
||||
return GetUserData(userId, item.Id, item.GetUserDataKeys());
|
||||
}
|
||||
|
||||
public UserItemDataDto GetUserDataDto(IHasUserData item, User user)
|
||||
|
|
|
@ -5,7 +5,9 @@ using MediaBrowser.Model.Logging;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -300,6 +302,52 @@ namespace MediaBrowser.Server.Implementations.Persistence
|
|||
}
|
||||
}
|
||||
|
||||
public UserItemData GetUserData(Guid userId, List<string> keys)
|
||||
{
|
||||
if (userId == Guid.Empty)
|
||||
{
|
||||
throw new ArgumentNullException("userId");
|
||||
}
|
||||
if (keys == null)
|
||||
{
|
||||
throw new ArgumentNullException("keys");
|
||||
}
|
||||
|
||||
using (var cmd = _connection.CreateCommand())
|
||||
{
|
||||
var index = 0;
|
||||
var excludeIds = new List<string>();
|
||||
var builder = new StringBuilder();
|
||||
foreach (var key in keys)
|
||||
{
|
||||
var paramName = "@Key" + index;
|
||||
excludeIds.Add("Key =" + paramName);
|
||||
cmd.Parameters.Add(cmd, paramName, DbType.String).Value = key;
|
||||
builder.Append(" WHEN Key=" + paramName + " THEN " + index);
|
||||
index++;
|
||||
}
|
||||
|
||||
var keyText = string.Join(" OR ", excludeIds.ToArray());
|
||||
|
||||
cmd.CommandText = "select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@userId AND (" + keyText + ") ";
|
||||
|
||||
cmd.CommandText += " ORDER BY (Case " + builder + " Else " + keys.Count.ToString(CultureInfo.InvariantCulture) + " End )";
|
||||
cmd.CommandText += " LIMIT 1";
|
||||
|
||||
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
|
||||
|
||||
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
|
||||
{
|
||||
if (reader.Read())
|
||||
{
|
||||
return ReadRow(reader);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return all user-data associated with the given user
|
||||
/// </summary>
|
||||
|
|
|
@ -111,24 +111,6 @@ namespace MediaBrowser.Server.Implementations.TV
|
|||
.Select(i => GetNextUp(i, currentUser))
|
||||
// Include if an episode was found, and either the series is not unwatched or the specific series was requested
|
||||
.Where(i => i.Item1 != null && (!i.Item3 || !string.IsNullOrWhiteSpace(request.SeriesId)))
|
||||
//.OrderByDescending(i =>
|
||||
//{
|
||||
// var episode = i.Item1;
|
||||
|
||||
// var seriesUserData = _userDataManager.GetUserData(user, episode.Series);
|
||||
|
||||
// if (seriesUserData.IsFavorite)
|
||||
// {
|
||||
// return 2;
|
||||
// }
|
||||
|
||||
// if (seriesUserData.Likes.HasValue)
|
||||
// {
|
||||
// return seriesUserData.Likes.Value ? 1 : -1;
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
//})
|
||||
.OrderByDescending(i => i.Item2)
|
||||
.ThenByDescending(i => i.Item1.PremiereDate ?? DateTime.MinValue)
|
||||
.Select(i => i.Item1);
|
||||
|
@ -143,9 +125,8 @@ namespace MediaBrowser.Server.Implementations.TV
|
|||
private Tuple<Episode, DateTime, bool> GetNextUp(Series series, User user)
|
||||
{
|
||||
// Get them in display order, then reverse
|
||||
var allEpisodes = series.GetSeasons(user, true, true)
|
||||
.Where(i => !i.IndexNumber.HasValue || i.IndexNumber.Value != 0)
|
||||
.SelectMany(i => i.GetEpisodes(user))
|
||||
var allEpisodes = series.GetEpisodes(user, true, true)
|
||||
.Where(i => !i.ParentIndexNumber.HasValue || i.ParentIndexNumber.Value != 0)
|
||||
.Reverse()
|
||||
.ToList();
|
||||
|
||||
|
@ -155,6 +136,8 @@ namespace MediaBrowser.Server.Implementations.TV
|
|||
|
||||
var includeMissing = user.Configuration.DisplayMissingEpisodes;
|
||||
|
||||
var unplayedEpisodes = new List<Episode>();
|
||||
|
||||
// Go back starting with the most recent episodes
|
||||
foreach (var episode in allEpisodes)
|
||||
{
|
||||
|
@ -172,6 +155,8 @@ namespace MediaBrowser.Server.Implementations.TV
|
|||
}
|
||||
else
|
||||
{
|
||||
unplayedEpisodes.Add(episode);
|
||||
|
||||
if (!episode.IsVirtualUnaired && (includeMissing || !episode.IsMissingEpisode))
|
||||
{
|
||||
nextUp = episode;
|
||||
|
@ -184,7 +169,18 @@ namespace MediaBrowser.Server.Implementations.TV
|
|||
return new Tuple<Episode, DateTime, bool>(nextUp, lastWatchedDate, false);
|
||||
}
|
||||
|
||||
var firstEpisode = allEpisodes.LastOrDefault(i => !i.IsVirtualUnaired && (includeMissing || !i.IsMissingEpisode) && !i.IsPlayed(user));
|
||||
Episode firstEpisode = null;
|
||||
// Find the first unplayed episode. Start from the back of the list since they're in reverse order
|
||||
for (var i = unplayedEpisodes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var unplayedEpisode = unplayedEpisodes[i];
|
||||
|
||||
if (!unplayedEpisode.IsVirtualUnaired && (includeMissing || !unplayedEpisode.IsMissingEpisode))
|
||||
{
|
||||
firstEpisode = unplayedEpisode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the first episode
|
||||
return new Tuple<Episode, DateTime, bool>(firstEpisode, DateTime.MinValue, true);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common.Internal</id>
|
||||
<version>3.0.649</version>
|
||||
<version>3.0.650</version>
|
||||
<title>MediaBrowser.Common.Internal</title>
|
||||
<authors>Luke</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
|
||||
<copyright>Copyright © Emby 2013</copyright>
|
||||
<dependencies>
|
||||
<dependency id="MediaBrowser.Common" version="3.0.649" />
|
||||
<dependency id="MediaBrowser.Common" version="3.0.650" />
|
||||
<dependency id="NLog" version="4.3.4" />
|
||||
<dependency id="SimpleInjector" version="3.1.5" />
|
||||
</dependencies>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Common</id>
|
||||
<version>3.0.649</version>
|
||||
<version>3.0.650</version>
|
||||
<title>MediaBrowser.Common</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>MediaBrowser.Server.Core</id>
|
||||
<version>3.0.649</version>
|
||||
<version>3.0.650</version>
|
||||
<title>Media Browser.Server.Core</title>
|
||||
<authors>Emby Team</authors>
|
||||
<owners>ebr,Luke,scottisafool</owners>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<description>Contains core components required to build plugins for Emby Server.</description>
|
||||
<copyright>Copyright © Emby 2013</copyright>
|
||||
<dependencies>
|
||||
<dependency id="MediaBrowser.Common" version="3.0.649" />
|
||||
<dependency id="MediaBrowser.Common" version="3.0.650" />
|
||||
<dependency id="Interfaces.IO" version="1.0.0.5" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
|
Loading…
Reference in a new issue