fixes #943 - Add web client filtering by genres, parental ratings, tags and years

This commit is contained in:
Luke Pulverenti 2014-11-09 23:20:11 -05:00
parent 1a80362a0f
commit 95eaf88abd
7 changed files with 182 additions and 70 deletions

View file

@ -193,13 +193,6 @@ namespace MediaBrowser.Api.UserLibrary
var filters = request.GetFilters().ToList();
if (filters.Count == 0)
{
return items;
}
items = items.AsParallel();
if (filters.Contains(ItemFilter.Dislikes))
{
items = items.Where(i =>
@ -243,9 +236,56 @@ namespace MediaBrowser.Api.UserLibrary
});
}
return items.AsEnumerable();
// Avoid implicitly captured closure
var currentRequest = request;
return items.Where(i => ApplyAdditionalFilters(currentRequest, i, user, false));
}
private bool ApplyAdditionalFilters(BaseItemsRequest request, BaseItem i, User user, bool isPreFiltered)
{
if (!isPreFiltered)
{
// Apply tag filter
var tags = request.GetTags();
if (tags.Length > 0)
{
var hasTags = i as IHasTags;
if (hasTags == null)
{
return false;
}
if (!(tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))))
{
return false;
}
}
// Apply official rating filter
var officialRatings = request.GetOfficialRatings();
if (officialRatings.Length > 0 && !officialRatings.Contains(i.OfficialRating ?? string.Empty))
{
return false;
}
// Apply genre filter
var genres = request.GetGenres();
if (genres.Length > 0 && !(genres.Any(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))))
{
return false;
}
// Apply year filter
var years = request.GetYears();
if (years.Length > 0 && !(i.ProductionYear.HasValue && years.Contains(i.ProductionYear.Value)))
{
return false;
}
}
return true;
}
/// <summary>
/// Filters the items.
/// </summary>

View file

@ -96,6 +96,41 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "IsPlayed", Description = "Optional filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsPlayed { get; set; }
/// <summary>
/// Limit results to items containing specific genres
/// </summary>
/// <value>The genres.</value>
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Genres { get; set; }
[ApiMember(Name = "OfficialRatings", Description = "Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string OfficialRatings { get; set; }
[ApiMember(Name = "Tags", Description = "Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Tags { get; set; }
/// <summary>
/// Limit results to items containing specific years
/// </summary>
/// <value>The years.</value>
[ApiMember(Name = "Years", Description = "Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Years { get; set; }
public string[] GetGenres()
{
return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetTags()
{
return (Tags ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetOfficialRatings()
{
return (OfficialRatings ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetMediaTypes()
{
return (MediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
@ -110,6 +145,11 @@ namespace MediaBrowser.Api.UserLibrary
{
return (ExcludeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
public int[] GetYears()
{
return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
}
/// <summary>
/// Gets the filters.

View file

@ -46,13 +46,6 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string PersonTypes { get; set; }
/// <summary>
/// Limit results to items containing specific genres
/// </summary>
/// <value>The genres.</value>
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Genres { get; set; }
[ApiMember(Name = "AllGenres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string AllGenres { get; set; }
@ -73,13 +66,6 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Albums { get; set; }
/// <summary>
/// Limit results to items containing specific years
/// </summary>
/// <value>The years.</value>
[ApiMember(Name = "Years", Description = "Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Years { get; set; }
/// <summary>
/// Gets or sets the item ids.
/// </summary>
@ -247,11 +233,6 @@ namespace MediaBrowser.Api.UserLibrary
return (AllGenres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetGenres()
{
return (Genres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
}
public string[] GetStudios()
{
return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
@ -262,11 +243,6 @@ namespace MediaBrowser.Api.UserLibrary
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
public int[] GetYears()
{
return (Years ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
}
public IEnumerable<VideoType> GetVideoTypes()
{
var val = VideoTypes;
@ -520,6 +496,8 @@ namespace MediaBrowser.Api.UserLibrary
HasThemeSong = request.HasThemeSong,
HasThemeVideo = request.HasThemeVideo,
HasTrailer = request.HasTrailer,
Tags = request.GetTags(),
OfficialRatings = request.GetOfficialRatings(),
Genres = request.GetGenres(),
AllGenres = request.GetAllGenres(),
Studios = request.GetStudios(),
@ -951,6 +929,28 @@ namespace MediaBrowser.Api.UserLibrary
}
}
// Apply tag filter
var tags = request.GetTags();
if (tags.Length > 0)
{
var hasTags = i as IHasTags;
if (hasTags == null)
{
return false;
}
if (!(tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))))
{
return false;
}
}
// Apply official rating filter
var officialRatings = request.GetOfficialRatings();
if (officialRatings.Length > 0 && !officialRatings.Contains(i.OfficialRating ?? string.Empty))
{
return false;
}
// Apply genre filter
var genres = request.GetGenres();
if (genres.Length > 0 && !(genres.Any(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))))

View file

@ -398,14 +398,16 @@ namespace MediaBrowser.Common.Implementations.IO
throw new ArgumentNullException("path");
}
//if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
// !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
//{
// return false;
//}
//return true;
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
return Path.IsPathRooted(path);
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
{
return false;
}
return true;
//return Path.IsPathRooted(path);
}
}
}

View file

@ -69,9 +69,13 @@ namespace MediaBrowser.Controller.Entities
public ImageType[] ImageTypes { get; set; }
public VideoType[] VideoTypes { get; set; }
public int[] Years { get; set; }
public string[] Tags { get; set; }
public string[] OfficialRatings { get; set; }
public InternalItemsQuery()
{
Tags = new string[] { };
OfficialRatings = new string[] { };
SortBy = new string[] { };
MediaTypes = new string[] { };
IncludeItemTypes = new string[] { };

View file

@ -870,6 +870,16 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (request.Tags.Length > 0)
{
return false;
}
if (request.OfficialRatings.Length > 0)
{
return false;
}
return true;
}
@ -1405,6 +1415,12 @@ namespace MediaBrowser.Controller.Entities
}
}
// Apply official rating filter
if (query.OfficialRatings.Length > 0 && !query.OfficialRatings.Contains(item.OfficialRating ?? string.Empty))
{
return false;
}
// Apply person filter
if (!string.IsNullOrEmpty(query.Person))
{
@ -1431,6 +1447,21 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
}
// Apply tag filter
var tags = query.Tags;
if (tags.Length > 0)
{
var hasTags = item as IHasTags;
if (hasTags == null)
{
return false;
}
if (!(tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))))
{
return false;
}
}
return true;

View file

@ -1,14 +1,9 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Server.Startup.Common.Browser;
using MediaBrowser.ServerApplication.Native;
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace MediaBrowser.ServerApplication
@ -17,18 +12,18 @@ namespace MediaBrowser.ServerApplication
{
bool IsDisposing = false;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem cmdExit;
private System.Windows.Forms.ToolStripMenuItem cmdBrowse;
private System.Windows.Forms.ToolStripMenuItem cmdConfigure;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
private System.Windows.Forms.ToolStripMenuItem cmdRestart;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem cmdCommunity;
private System.Windows.Forms.ToolStripMenuItem cmdApiDocs;
private System.Windows.Forms.ToolStripMenuItem cmdSwagger;
private System.Windows.Forms.ToolStripMenuItem cmdGtihub;
private NotifyIcon notifyIcon1;
private ContextMenuStrip contextMenuStrip1;
private ToolStripMenuItem cmdExit;
private ToolStripMenuItem cmdBrowse;
private ToolStripMenuItem cmdConfigure;
private ToolStripSeparator toolStripSeparator2;
private ToolStripMenuItem cmdRestart;
private ToolStripSeparator toolStripSeparator1;
private ToolStripMenuItem cmdCommunity;
private ToolStripMenuItem cmdApiDocs;
private ToolStripMenuItem cmdSwagger;
private ToolStripMenuItem cmdGtihub;
private readonly ILogger _logger;
private readonly IServerApplicationHost _appHost;
@ -61,19 +56,19 @@ namespace MediaBrowser.ServerApplication
var components = new System.ComponentModel.Container();
var resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(components);
notifyIcon1 = new System.Windows.Forms.NotifyIcon(components);
contextMenuStrip1 = new ContextMenuStrip(components);
notifyIcon1 = new NotifyIcon(components);
cmdExit = new System.Windows.Forms.ToolStripMenuItem();
cmdCommunity = new System.Windows.Forms.ToolStripMenuItem();
toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
cmdRestart = new System.Windows.Forms.ToolStripMenuItem();
toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
cmdConfigure = new System.Windows.Forms.ToolStripMenuItem();
cmdBrowse = new System.Windows.Forms.ToolStripMenuItem();
cmdApiDocs = new System.Windows.Forms.ToolStripMenuItem();
cmdSwagger = new System.Windows.Forms.ToolStripMenuItem();
cmdGtihub = new System.Windows.Forms.ToolStripMenuItem();
cmdExit = new ToolStripMenuItem();
cmdCommunity = new ToolStripMenuItem();
toolStripSeparator1 = new ToolStripSeparator();
cmdRestart = new ToolStripMenuItem();
toolStripSeparator2 = new ToolStripSeparator();
cmdConfigure = new ToolStripMenuItem();
cmdBrowse = new ToolStripMenuItem();
cmdApiDocs = new ToolStripMenuItem();
cmdSwagger = new ToolStripMenuItem();
cmdGtihub = new ToolStripMenuItem();
//
// notifyIcon1
@ -85,7 +80,7 @@ namespace MediaBrowser.ServerApplication
//
// contextMenuStrip1
//
contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
contextMenuStrip1.Items.AddRange(new ToolStripItem[] {
cmdBrowse,
cmdConfigure,
toolStripSeparator2,
@ -136,7 +131,7 @@ namespace MediaBrowser.ServerApplication
//
// cmdApiDocs
//
cmdApiDocs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
cmdApiDocs.DropDownItems.AddRange(new ToolStripItem[] {
cmdSwagger,
cmdGtihub});
cmdApiDocs.Name = "cmdApiDocs";