jellyfin/MediaBrowser.Api/Reports/ReportsService.cs

487 lines
20 KiB
C#
Raw Normal View History

2016-03-27 21:11:27 +00:00
using MediaBrowser.Controller.Entities;
2015-02-07 03:25:39 +00:00
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Querying;
2015-04-17 19:12:25 +00:00
using System.Collections.Generic;
2015-02-07 03:25:39 +00:00
using System.Threading.Tasks;
2015-04-17 19:12:25 +00:00
using System.Globalization;
using System.Linq;
using MediaBrowser.Controller.Localization;
using System;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Activity;
using MediaBrowser.Controller.Activity;
2015-02-07 03:25:39 +00:00
namespace MediaBrowser.Api.Reports
{
2015-06-30 18:38:09 +00:00
/// <summary> The reports service. </summary>
/// <seealso cref="T:MediaBrowser.Api.BaseApiService"/>
public class ReportsService : BaseApiService
{
#region [Constructors]
/// <summary>
/// Initializes a new instance of the MediaBrowser.Api.Reports.ReportsService class. </summary>
/// <param name="userManager"> Manager for user. </param>
/// <param name="libraryManager"> Manager for library. </param>
/// <param name="localization"> The localization. </param>
/// <param name="activityManager"> Manager for activity. </param>
public ReportsService(IUserManager userManager, ILibraryManager libraryManager, ILocalizationManager localization, IActivityManager activityManager, IActivityRepository repo)
{
_userManager = userManager;
_libraryManager = libraryManager;
_localization = localization;
_activityManager = activityManager;
_repo = repo;
}
#endregion
#region [Private Fields]
private readonly IActivityManager _activityManager; ///< Manager for activity
/// <summary> Manager for library. </summary>
private readonly ILibraryManager _libraryManager; ///< Manager for library
2016-07-15 19:54:34 +00:00
/// <summary> The localization. </summary>
2015-06-30 18:38:09 +00:00
private readonly ILocalizationManager _localization; ///< The localization
private readonly IActivityRepository _repo;
/// <summary> Manager for user. </summary>
private readonly IUserManager _userManager; ///< Manager for user
#endregion
#region [Public Methods]
/// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns>
2016-07-15 19:54:34 +00:00
public object Get(GetActivityLogs request)
2015-06-30 18:38:09 +00:00
{
request.DisplayType = "Screen";
2016-07-15 19:54:34 +00:00
ReportResult result = GetReportActivities(request);
2015-06-30 18:38:09 +00:00
return ToOptimizedResult(result);
}
/// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns>
public async Task<object> Get(GetReportHeaders request)
{
if (string.IsNullOrEmpty(request.IncludeItemTypes))
return null;
request.DisplayType = "Screen";
2015-06-30 18:38:09 +00:00
ReportViewType reportViewType = ReportHelper.GetReportViewType(request.ReportView);
List<ReportHeader> result = new List<ReportHeader>();
switch (reportViewType)
{
case ReportViewType.ReportData:
ReportBuilder dataBuilder = new ReportBuilder(_libraryManager);
result = dataBuilder.GetHeaders(request);
break;
case ReportViewType.ReportStatistics:
break;
case ReportViewType.ReportActivities:
ReportActivitiesBuilder activityBuilder = new ReportActivitiesBuilder(_libraryManager, _userManager);
result = activityBuilder.GetHeaders(request);
break;
}
return ToOptimizedResult(result);
}
/// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns>
public async Task<object> Get(GetItemReport request)
{
if (string.IsNullOrEmpty(request.IncludeItemTypes))
return null;
request.DisplayType = "Screen";
2016-07-15 19:54:34 +00:00
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var reportResult = await GetReportResult(request, user);
2015-06-30 18:38:09 +00:00
return ToOptimizedResult(reportResult);
}
/// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns>
public async Task<object> Get(GetReportStatistics request)
{
if (string.IsNullOrEmpty(request.IncludeItemTypes))
return null;
request.DisplayType = "Screen";
2016-07-15 19:54:34 +00:00
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
var reportResult = await GetReportStatistic(request, user);
2015-06-30 18:38:09 +00:00
return ToOptimizedResult(reportResult);
}
/// <summary> Gets the given request. </summary>
/// <param name="request"> The request. </param>
/// <returns> A Task&lt;object&gt; </returns>
public async Task<object> Get(GetReportDownload request)
{
if (string.IsNullOrEmpty(request.IncludeItemTypes))
return null;
request.DisplayType = "Export";
2015-06-30 18:38:09 +00:00
ReportViewType reportViewType = ReportHelper.GetReportViewType(request.ReportView);
var headers = new Dictionary<string, string>();
string fileExtension = "csv";
string contentType = "text/plain;charset='utf-8'";
switch (request.ExportType)
{
case ReportExportType.CSV:
break;
case ReportExportType.Excel:
contentType = "application/vnd.ms-excel";
fileExtension = "xls";
break;
}
var filename = "ReportExport." + fileExtension;
headers["Content-Disposition"] = string.Format("attachment; filename=\"{0}\"", filename);
headers["Content-Encoding"] = "UTF-8";
2016-07-15 19:54:34 +00:00
var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
2015-06-30 18:38:09 +00:00
ReportResult result = null;
switch (reportViewType)
{
case ReportViewType.ReportStatistics:
case ReportViewType.ReportData:
ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
ReportBuilder dataBuilder = new ReportBuilder(_libraryManager);
2016-07-15 19:54:34 +00:00
QueryResult<BaseItem> queryResult = await GetQueryResult(request, user).ConfigureAwait(false);
2015-06-30 18:38:09 +00:00
result = dataBuilder.GetResult(queryResult.Items, request);
result.TotalRecordCount = queryResult.TotalRecordCount;
break;
case ReportViewType.ReportActivities:
2016-07-15 19:54:34 +00:00
result = GetReportActivities(request);
2015-06-30 18:38:09 +00:00
break;
}
string returnResult = string.Empty;
switch (request.ExportType)
{
case ReportExportType.CSV:
returnResult = new ReportExport().ExportToCsv(result);
break;
case ReportExportType.Excel:
returnResult = new ReportExport().ExportToExcel(result);
break;
}
2016-07-15 19:54:34 +00:00
return ResultFactory.GetResult(returnResult, contentType, headers);
2015-06-30 18:38:09 +00:00
}
#endregion
private InternalItemsQuery GetItemsQuery(BaseReportRequest request, User user)
{
2016-07-15 19:54:34 +00:00
var query = new InternalItemsQuery(user)
{
IsPlayed = request.IsPlayed,
MediaTypes = request.GetMediaTypes(),
IncludeItemTypes = request.GetIncludeItemTypes(),
ExcludeItemTypes = request.GetExcludeItemTypes(),
Recursive = request.Recursive,
SortBy = request.GetOrderBy(),
SortOrder = request.SortOrder ?? SortOrder.Ascending,
2015-06-30 18:38:09 +00:00
IsFavorite = request.IsFavorite,
Limit = request.Limit,
StartIndex = request.StartIndex,
IsMissing = request.IsMissing,
IsVirtualUnaired = request.IsVirtualUnaired,
IsUnaired = request.IsUnaired,
CollapseBoxSetItems = request.CollapseBoxSetItems,
NameLessThan = request.NameLessThan,
NameStartsWith = request.NameStartsWith,
NameStartsWithOrGreater = request.NameStartsWithOrGreater,
HasImdbId = request.HasImdbId,
IsPlaceHolder = request.IsPlaceHolder,
IsLocked = request.IsLocked,
IsInBoxSet = request.IsInBoxSet,
IsHD = request.IsHD,
Is3D = request.Is3D,
HasTvdbId = request.HasTvdbId,
HasTmdbId = request.HasTmdbId,
HasOverview = request.HasOverview,
HasOfficialRating = request.HasOfficialRating,
HasParentalRating = request.HasParentalRating,
HasSpecialFeature = request.HasSpecialFeature,
HasSubtitles = request.HasSubtitles,
HasThemeSong = request.HasThemeSong,
HasThemeVideo = request.HasThemeVideo,
HasTrailer = request.HasTrailer,
Tags = request.GetTags(),
OfficialRatings = request.GetOfficialRatings(),
Genres = request.GetGenres(),
2016-07-15 19:54:34 +00:00
GenreIds = request.GetGenreIds(),
Studios = request.GetStudios(),
StudioIds = request.GetStudioIds(),
Person = request.Person,
PersonIds = request.GetPersonIds(),
PersonTypes = request.GetPersonTypes(),
Years = request.GetYears(),
ImageTypes = request.GetImageTypes().ToArray(),
VideoTypes = request.GetVideoTypes().ToArray(),
AdjacentTo = request.AdjacentTo,
ItemIds = request.GetItemIds(),
MinPlayers = request.MinPlayers,
MaxPlayers = request.MaxPlayers,
MinCommunityRating = request.MinCommunityRating,
2016-03-20 19:53:22 +00:00
MinCriticRating = request.MinCriticRating,
2016-07-15 19:54:34 +00:00
ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId),
2016-03-20 20:04:27 +00:00
ParentIndexNumber = request.ParentIndexNumber,
2016-03-21 00:15:56 +00:00
AiredDuringSeason = request.AiredDuringSeason,
2016-07-15 19:54:34 +00:00
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater,
EnableTotalRecordCount = request.EnableTotalRecordCount
};
2015-06-30 18:38:09 +00:00
if (!string.IsNullOrWhiteSpace(request.Ids))
{
query.CollapseBoxSetItems = false;
2015-06-30 18:38:09 +00:00
}
foreach (var filter in request.GetFilters())
2015-06-30 18:38:09 +00:00
{
switch (filter)
2015-06-30 18:38:09 +00:00
{
case ItemFilter.Dislikes:
query.IsLiked = false;
break;
case ItemFilter.IsFavorite:
query.IsFavorite = true;
break;
case ItemFilter.IsFavoriteOrLikes:
query.IsFavoriteOrLiked = true;
break;
case ItemFilter.IsFolder:
query.IsFolder = true;
break;
case ItemFilter.IsNotFolder:
query.IsFolder = false;
break;
case ItemFilter.IsPlayed:
query.IsPlayed = true;
break;
case ItemFilter.IsRecentlyAdded:
break;
case ItemFilter.IsResumable:
query.IsResumable = true;
break;
case ItemFilter.IsUnplayed:
query.IsPlayed = false;
break;
case ItemFilter.Likes:
query.IsLiked = true;
break;
2015-06-30 18:38:09 +00:00
}
}
2016-03-20 06:46:51 +00:00
if (!string.IsNullOrEmpty(request.MinPremiereDate))
{
query.MinPremiereDate = DateTime.Parse(request.MinPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
if (!string.IsNullOrEmpty(request.MaxPremiereDate))
{
query.MaxPremiereDate = DateTime.Parse(request.MaxPremiereDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
2016-03-20 19:53:22 +00:00
// Filter by Series Status
if (!string.IsNullOrEmpty(request.SeriesStatus))
{
query.SeriesStatuses = request.SeriesStatus.Split(',').Select(d => (SeriesStatus)Enum.Parse(typeof(SeriesStatus), d, true)).ToArray();
}
// Filter by Series AirDays
if (!string.IsNullOrEmpty(request.AirDays))
{
query.AirDays = request.AirDays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d, true)).ToArray();
}
// ExcludeLocationTypes
if (!string.IsNullOrEmpty(request.ExcludeLocationTypes))
{
query.ExcludeLocationTypes = request.ExcludeLocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
if (!string.IsNullOrEmpty(request.LocationTypes))
{
query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
}
2016-03-21 03:10:37 +00:00
// Min official rating
2016-04-27 17:50:32 +00:00
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
2016-03-21 03:10:37 +00:00
{
query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating);
}
// Max official rating
2016-04-27 17:50:32 +00:00
if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating))
2016-03-21 03:10:37 +00:00
{
2016-04-27 17:50:32 +00:00
query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating);
2016-03-21 03:10:37 +00:00
}
2016-03-22 03:35:24 +00:00
// Artists
if (!string.IsNullOrEmpty(request.ArtistIds))
{
var artistIds = request.ArtistIds.Split(new[] { '|', ',' });
var artistItems = artistIds.Select(_libraryManager.GetItemById).Where(i => i != null).ToList();
query.ArtistNames = artistItems.Select(i => i.Name).ToArray();
}
2016-03-21 16:50:50 +00:00
// Artists
if (!string.IsNullOrEmpty(request.Artists))
{
query.ArtistNames = request.Artists.Split('|');
}
// Albums
if (!string.IsNullOrEmpty(request.Albums))
{
query.AlbumNames = request.Albums.Split('|');
}
return query;
}
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
private async Task<QueryResult<BaseItem>> GetQueryResult(BaseReportRequest request, User user)
2015-06-30 18:38:09 +00:00
{
2016-07-15 19:54:34 +00:00
// all report queries currently need this because it's not being specified
2015-06-30 18:38:09 +00:00
request.Recursive = true;
var item = string.IsNullOrEmpty(request.ParentId) ?
user == null ? _libraryManager.RootFolder : user.RootFolder :
2016-07-15 19:54:34 +00:00
_libraryManager.GetItemById(request.ParentId);
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase))
{
//item = user == null ? _libraryManager.RootFolder : user.RootFolder;
}
else if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase))
{
item = user == null ? _libraryManager.RootFolder : user.RootFolder;
}
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
// Default list type = children
var folder = item as Folder;
if (folder == null)
2015-06-30 18:38:09 +00:00
{
2016-07-15 19:54:34 +00:00
folder = user == null ? _libraryManager.RootFolder : _libraryManager.GetUserRootFolder();
2015-06-30 18:38:09 +00:00
}
2016-07-15 19:54:34 +00:00
if (!string.IsNullOrEmpty(request.Ids))
2015-06-30 18:38:09 +00:00
{
2016-07-15 19:54:34 +00:00
request.Recursive = true;
var query = GetItemsQuery(request, user);
var result = await folder.GetItems(query).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(request.SortBy))
2015-06-30 18:38:09 +00:00
{
2016-07-15 19:54:34 +00:00
var ids = query.ItemIds.ToList();
// Try to preserve order
result.Items = result.Items.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
2015-06-30 18:38:09 +00:00
}
2016-07-15 19:54:34 +00:00
return result;
}
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
if (request.Recursive)
{
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
}
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
if (user == null)
{
return await folder.GetItems(GetItemsQuery(request, null)).ConfigureAwait(false);
}
var userRoot = item as UserRootFolder;
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
if (userRoot == null)
{
return await folder.GetItems(GetItemsQuery(request, user)).ConfigureAwait(false);
2015-06-30 18:38:09 +00:00
}
2016-07-15 19:54:34 +00:00
IEnumerable<BaseItem> items = folder.GetChildren(user, true);
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
var itemsArray = items.ToArray();
return new QueryResult<BaseItem>
{
Items = itemsArray,
TotalRecordCount = itemsArray.Length
};
2015-06-30 18:38:09 +00:00
}
2016-07-15 19:54:34 +00:00
#region [Private Methods]
2015-06-30 18:38:09 +00:00
/// <summary> Gets report activities. </summary>
/// <param name="request"> The request. </param>
/// <returns> The report activities. </returns>
2016-07-15 19:54:34 +00:00
private ReportResult GetReportActivities(IReportsDownload request)
2015-06-30 18:38:09 +00:00
{
2016-07-15 19:54:34 +00:00
DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
(DateTime?)null :
DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
QueryResult<ActivityLogEntry> queryResult;
if (request.HasQueryLimit)
queryResult = _repo.GetActivityLogEntries(minDate, request.StartIndex, request.Limit);
else
queryResult = _repo.GetActivityLogEntries(minDate, request.StartIndex, null);
//var queryResult = _activityManager.GetActivityLogEntries(minDate, request.StartIndex, request.Limit);
2015-06-30 18:38:09 +00:00
2016-07-15 19:54:34 +00:00
ReportActivitiesBuilder builder = new ReportActivitiesBuilder(_libraryManager, _userManager);
var result = builder.GetResult(queryResult, request);
result.TotalRecordCount = queryResult.TotalRecordCount;
return result;
2015-06-30 18:38:09 +00:00
}
/// <summary> Gets report result. </summary>
/// <param name="request"> The request. </param>
/// <returns> The report result. </returns>
2016-07-15 19:54:34 +00:00
private async Task<ReportResult> GetReportResult(GetItemReport request, User user)
2015-06-30 18:38:09 +00:00
{
ReportBuilder reportBuilder = new ReportBuilder(_libraryManager);
2016-07-15 19:54:34 +00:00
QueryResult<BaseItem> queryResult = await GetQueryResult(request, user).ConfigureAwait(false);
2015-06-30 18:38:09 +00:00
ReportResult reportResult = reportBuilder.GetResult(queryResult.Items, request);
reportResult.TotalRecordCount = queryResult.TotalRecordCount;
return reportResult;
}
/// <summary> Gets report statistic. </summary>
/// <param name="request"> The request. </param>
/// <returns> The report statistic. </returns>
2016-07-15 19:54:34 +00:00
private async Task<ReportStatResult> GetReportStatistic(GetReportStatistics request, User user)
2015-06-30 18:38:09 +00:00
{
ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes);
2016-07-15 19:54:34 +00:00
QueryResult<BaseItem> queryResult = await GetQueryResult(request, user).ConfigureAwait(false);
2015-06-30 18:38:09 +00:00
ReportStatBuilder reportBuilder = new ReportStatBuilder(_libraryManager);
ReportStatResult reportResult = reportBuilder.GetResult(queryResult.Items, ReportHelper.GetRowType(request.IncludeItemTypes), request.TopItems ?? 5);
reportResult.TotalRecordCount = reportResult.Groups.Count();
return reportResult;
}
#endregion
}
2015-02-07 03:25:39 +00:00
}