Skip to content

Commit fbf6fda

Browse files
committed
wip search upates
1 parent 2ddb6f3 commit fbf6fda

File tree

18 files changed

+449
-143
lines changed

18 files changed

+449
-143
lines changed

Source/Plex.Api/Api/ApiRequest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public string FullUri
8181

8282
if (!string.IsNullOrEmpty(this.Endpoint))
8383
{
84-
uriBuilder.Append(this.Endpoint.StartsWith("/") ? this.Endpoint.Skip(1) : this.Endpoint);
84+
uriBuilder.Append(this.Endpoint.StartsWith("/") ? this.Endpoint.Substring(1) : this.Endpoint);
8585
}
8686

8787
this.AddQueryParams(uriBuilder);

Source/Plex.Api/Api/ApiRequestBuilder.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
namespace Plex.Api.Api
22
{
3+
using System;
34
using System.Collections.Generic;
45
using System.Linq;
56
using System.Net.Http;
7+
using ApiModels.Libraries.Filters;
68

79
/// <summary>
810
/// Api Request Builder.
@@ -112,6 +114,52 @@ public ApiRequestBuilder AddJsonBody(object body)
112114
return this;
113115
}
114116

117+
/// <summary>
118+
/// Add Filter Parameters
119+
/// </summary>
120+
/// <param name="filters">Field Filter Requests</param>
121+
public ApiRequestBuilder AddFilterFields(List<FilterRequest> filters)
122+
{
123+
if (filters != null && filters.Any())
124+
{
125+
var queryParameters = this.queryParams ?? new Dictionary<string, string>();
126+
127+
foreach (var item in filters)
128+
{
129+
switch (item.Operator)
130+
{
131+
case Operator.Is:
132+
queryParameters.Add(item.Field, string.Join(",", item.Values));
133+
break;
134+
case Operator.IsNot:
135+
queryParameters.Add(item.Field+"!", string.Join(",", item.Values));
136+
break;
137+
case Operator.GreaterThan:
138+
queryParameters.Add(item.Field+">>", string.Join(",", item.Values));
139+
break;
140+
case Operator.LessThan:
141+
queryParameters.Add(item.Field+"<<", string.Join(",", item.Values));
142+
break;
143+
case Operator.Contains:
144+
queryParameters.Add(item.Field+"=", string.Join(",", item.Values));
145+
break;
146+
case Operator.NotContains:
147+
queryParameters.Add(item.Field+"!=", string.Join(",", item.Values));
148+
break;
149+
case Operator.BeginsWith:
150+
queryParameters.Add(item.Field+"<", string.Join(",", item.Values));
151+
break;
152+
case Operator.EndsWith:
153+
queryParameters.Add(item.Field+">", string.Join(",", item.Values));
154+
break;
155+
default:
156+
throw new ApplicationException("Invalid Operator requested.");
157+
}
158+
}
159+
}
160+
return this;
161+
}
162+
115163
private void AddSingleHeader(string key, string value)
116164
{
117165
var headers = this.requestHeaders ?? new Dictionary<string, string>();
@@ -152,5 +200,7 @@ private void AddSingleQueryParam(string key, string value)
152200
public ApiRequest Build() =>
153201
new ApiRequest(this.endpoint, this.baseUri, this.httpMethod, this.requestHeaders, this.contentHeaders, this.Body,
154202
this.queryParams);
203+
204+
155205
}
156206
}

Source/Plex.Api/ApiModels/Libraries/Filters/FilterModel.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@ namespace Plex.Api.ApiModels.Libraries.Filters
33
using System.Collections.Generic;
44
using PlexModels.Library.Search;
55

6-
public class FilterModelContainer
7-
{
8-
}
9-
106
/// <summary>
117
/// Filter
128
/// "key": "/library/sections/1/all?type=1",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace Plex.Api.ApiModels.Libraries.Filters
2+
{
3+
using System.Collections.Generic;
4+
5+
public class FilterRequest
6+
{
7+
public string Field { get; set; }
8+
public Operator Operator { get; set; }
9+
public List<string> Values { get; set; }
10+
}
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace Plex.Api.ApiModels.Libraries.Filters
2+
{
3+
public enum Operator
4+
{
5+
Is,
6+
IsNot,
7+
Contains,
8+
NotContains,
9+
GreaterThan,
10+
LessThan,
11+
BeginsWith,
12+
EndsWith
13+
}
14+
}

Source/Plex.Api/ApiModels/Libraries/LibraryBase.cs

Lines changed: 116 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ namespace Plex.Api.ApiModels.Libraries
1010
using Helpers.Mappings;
1111
using PlexModels.Hubs;
1212
using PlexModels.Library.Search;
13-
using PlexModels.Library.Search.Plex.Api.PlexModels.Library.Search;
1413
using PlexModels.Media;
1514

1615
/// <summary>
@@ -19,31 +18,37 @@ namespace Plex.Api.ApiModels.Libraries
1918
public class LibraryBase
2019
{
2120
/// <summary>
22-
///
21+
/// Filters
2322
/// </summary>
24-
public readonly IPlexServerClient PlexServerClient;
23+
private List<FilterModel> _filters;
2524

2625
/// <summary>
2726
///
2827
/// </summary>
29-
public readonly IPlexLibraryClient PlexLibraryClient;
28+
public readonly IPlexServerClient _plexServerClient;
3029

3130
/// <summary>
3231
///
3332
/// </summary>
34-
protected readonly Server Server;
33+
public readonly IPlexLibraryClient _plexLibraryClient;
3534

3635
/// <summary>
3736
///
3837
/// </summary>
38+
protected readonly Server _server;
39+
40+
/// <summary>
41+
/// This will become the Base Object for All Plex Libraries.
42+
/// When we instantiate a library, we will pull all the Filter Fields, Sorts and Operators
43+
/// </summary>
3944
/// <param name="plexServerClient"></param>
4045
/// <param name="plexLibraryClient"></param>
4146
/// <param name="server"></param>
4247
public LibraryBase(IPlexServerClient plexServerClient, IPlexLibraryClient plexLibraryClient, Server server)
4348
{
44-
this.PlexServerClient = plexServerClient ?? throw new ArgumentNullException(nameof(plexServerClient));
45-
this.PlexLibraryClient = plexLibraryClient ?? throw new ArgumentNullException(nameof(plexLibraryClient));
46-
this.Server = server ?? throw new ArgumentNullException(nameof(server));
49+
this._plexServerClient = plexServerClient ?? throw new ArgumentNullException(nameof(plexServerClient));
50+
this._plexLibraryClient = plexLibraryClient ?? throw new ArgumentNullException(nameof(plexLibraryClient));
51+
this._server = server ?? throw new ArgumentNullException(nameof(server));
4752
}
4853

4954
public bool HasFilters { get; }
@@ -77,32 +82,102 @@ public LibraryBase(IPlexServerClient plexServerClient, IPlexLibraryClient plexLi
7782
public DateTime UpdatedAt { get; set; }
7883

7984
public List<string> Locations { get; set; }
80-
public List<Filter> Filters { get; set; }
85+
86+
87+
8188

8289
/// <summary>
83-
/// Get Filters available for this Library
90+
/// Library Filter Fields
8491
/// </summary>
85-
/// <returns>List of FilterField</returns>
86-
private async Task<FilterContainer> GetFilters()
92+
public List<FilterModel> FilterFields
8793
{
88-
var filterContainer = await this.PlexLibraryClient.GetLibraryFilters(this.Server.AccessToken, this.Server.Uri.ToString(),
89-
this.Key);
94+
get
95+
{
96+
if (this._filters != null)
97+
{
98+
return this._filters;
99+
}
100+
101+
var filterContainer = this._plexLibraryClient.GetFilterFields(this._server.AccessToken, this._server.Uri.ToString(),
102+
this.Key).Result;
103+
104+
this._filters = LibraryFilterMapper.GetFilterModelsFromFilterContainer(filterContainer);
90105

91-
return filterContainer;
106+
return this._filters;
107+
}
92108
}
93109

94110
/// <summary>
95-
/// Get Filters available for this Library
111+
/// Get Filter Values for given FieldType and FieldKey
96112
/// </summary>
97-
/// <returns>List of FilterField</returns>
98-
public async Task<List<FilterModel>> FilterFields()
113+
/// <param name="fieldType">Field Type (movie, library, artist, album)</param>
114+
/// <param name="fieldKey">Field Key (ex: genre, year)</param>
115+
/// <param name="title">Title of Field Value</param>
116+
/// <returns></returns>
117+
/// <exception cref="ApplicationException"></exception>
118+
public async Task<List<FilterValue>> GetFilterValues(string fieldType, string fieldKey, string title)
99119
{
100-
var filterFieldContainer = await this.PlexLibraryClient.GetFilterFields(this.Server.AccessToken, this.Server.Uri.ToString(),
101-
this.Key);
120+
// // Check to see if these values are already in cache.
121+
// if (this._filterValues.ContainsKey(fieldType + "_" + fieldKey))
122+
// {
123+
// if (!string.IsNullOrEmpty(title))
124+
// {
125+
// return this._filterValues[fieldType + "_" + fieldKey]
126+
// .Where(c=>c.Title.Contains(title))
127+
// .ToList();
128+
// }
129+
// return this._filterValues[fieldType + "_" + fieldKey];
130+
// }
131+
132+
// Get Filter
133+
var filterField = this.FilterFields
134+
.SingleOrDefault(g=> g.Type == fieldType);
135+
136+
if (filterField == null)
137+
{
138+
throw new ApplicationException("Invalid Filter FieldType: " + fieldType);
139+
}
140+
141+
if (filterField.FilterFields == null || !filterField.FilterFields.Any())
142+
{
143+
throw new ApplicationException("Invalid Filter FieldKey: " + fieldKey);
144+
}
145+
146+
var item = filterField.FilterFields
147+
.SingleOrDefault(t => t.FieldKey == fieldKey);
148+
149+
if (item == null)
150+
{
151+
throw new ApplicationException("Invalid Filter FieldKey: " + fieldKey);
152+
}
102153

103-
return LibraryFilterMapper.GetFilterModelsFromFilterContainer(filterFieldContainer);
154+
var filterValueContainer = await this._plexLibraryClient.GetLibraryFilterValues(this._server.AccessToken,
155+
this._server.Uri.ToString(), this.Key, item.UriKey);
156+
157+
// this._filterValues.Add(fieldType + "_" + fieldKey, filterValueContainer.FilterValues);
158+
159+
if (!string.IsNullOrEmpty(title))
160+
{
161+
return filterValueContainer.FilterValues
162+
.Where(c=>c.Title.Contains(title))
163+
.ToList();
164+
}
165+
166+
return filterValueContainer.FilterValues;
104167
}
105168

169+
// /// <summary>
170+
// /// Get Filters available for this Library
171+
// /// </summary>
172+
// /// <returns>List of FilterField</returns>
173+
// public async Task<List<FilterModel>> FilterFields()
174+
// {
175+
// var filterFieldContainer = await this.PlexLibraryClient.GetFilterFields(this.Server.AccessToken, this.Server.Uri.ToString(),
176+
// this.Key);
177+
//
178+
// return LibraryFilterMapper.GetFilterModelsFromFilterContainer(filterFieldContainer);
179+
// }
180+
106181
/// <summary>
107182
/// Matching Library Items with Metadata
108183
/// </summary>
@@ -133,10 +208,11 @@ public async Task<List<FilterModel>> FilterFields()
133208
/// <param name="count">Only return the specified number of results (default 100).</param>
134209
/// <returns>MediaContainer</returns>
135210
public async Task<MediaContainer> Search(bool includeExtendedMetadata, string title, string sort, SearchType? libraryType,
136-
Dictionary<string, string> filters = null, int start = 0, int count = 100)
211+
List<FilterRequest> filters = null, int start = 0, int count = 100)
137212
{
213+
// TODO Validate Operators if used
138214
var librarySummaryContainer =
139-
await this.PlexLibraryClient.LibrarySearch(this.Server.AccessToken, this.Server.Uri.ToString(),
215+
await this._plexLibraryClient.LibrarySearch(this._server.AccessToken, this._server.Uri.ToString(),
140216
title, this.Key, sort, libraryType, filters, start, count);
141217

142218
if (librarySummaryContainer != null && librarySummaryContainer.Size > 0)
@@ -145,8 +221,8 @@ await this.PlexLibraryClient.LibrarySearch(this.Server.AccessToken, this.Server.
145221
{
146222
for (var i = 0; i < librarySummaryContainer.Media.Count; i++)
147223
{
148-
var mediaContainer = await this.PlexLibraryClient.GetItem(this.Server.AccessToken,
149-
this.Server.Uri.ToString(),
224+
var mediaContainer = await this._plexLibraryClient.GetItem(this._server.AccessToken,
225+
this._server.Uri.ToString(),
150226
librarySummaryContainer.Media[i].RatingKey);
151227
librarySummaryContainer.Media[i] = mediaContainer.Media.First();
152228
}
@@ -178,61 +254,61 @@ public async Task<MediaContainer> All(bool includeExtendedMetadata, SearchType l
178254
/// <param name="count">Max number of items to return</param>
179255
/// <returns></returns>
180256
protected async Task<MediaContainer> RecentlyAdded(SearchType libraryType, int start, int count) =>
181-
await this.PlexServerClient.GetLibraryRecentlyAddedAsync(this.Server.AccessToken,
182-
this.Server.Uri.ToString(), libraryType, this.Key, start, count);
257+
await this._plexServerClient.GetLibraryRecentlyAddedAsync(this._server.AccessToken,
258+
this._server.Uri.ToString(), libraryType, this.Key, start, count);
183259

184260
/// <summary>
185261
/// Return list of Hubs on this library along with their Metadata items
186262
/// </summary>
187263
/// <param name="count">Max count of items on each hub</param>
188264
/// <returns></returns>
189265
public async Task<HubMediaContainer> Hubs(int count = 10) =>
190-
await this.PlexServerClient.GetLibraryHubAsync(this.Server.AccessToken, this.Server.Uri.ToString(),
266+
await this._plexServerClient.GetLibraryHubAsync(this._server.AccessToken, this._server.Uri.ToString(),
191267
this.Key, count);
192268

193269
/// <summary>
194270
/// Empty Trash for this Library
195271
/// </summary>
196272
public async Task EmptyTrash() =>
197-
await this.PlexLibraryClient.EmptyTrash(this.Server.AccessToken, this.Server.Uri.ToString(), this.Key);
273+
await this._plexLibraryClient.EmptyTrash(this._server.AccessToken, this._server.Uri.ToString(), this.Key);
198274

199275
/// <summary>
200276
/// Scan for new items on this Library
201277
/// </summary>
202278
public async Task ScanForNewItems(bool forceMetadataRefresh) =>
203-
await this.PlexLibraryClient.ScanForNewItems(this.Server.AccessToken, this.Server.Uri.ToString(), this.Key,
279+
await this._plexLibraryClient.ScanForNewItems(this._server.AccessToken, this._server.Uri.ToString(), this.Key,
204280
forceMetadataRefresh);
205281

206282
/// <summary>
207283
/// Cancel running Scan on this library
208284
/// </summary>
209285
public async Task CancelScan() =>
210-
await this.PlexLibraryClient.CancelScanForNewItems(this.Server.AccessToken, this.Server.Uri.ToString(),
286+
await this._plexLibraryClient.CancelScanForNewItems(this._server.AccessToken, this._server.Uri.ToString(),
211287
this.Key);
212288

213289
/// <summary>
214290
/// Get Total Number of Items in Library
215291
/// </summary>
216292
/// <returns>Size of library</returns>
217293
public async Task<int> Size() =>
218-
await this.PlexLibraryClient.GetLibrarySize(this.Server.AccessToken, this.Server.Uri.ToString(), this.Key);
294+
await this._plexLibraryClient.GetLibrarySize(this._server.AccessToken, this._server.Uri.ToString(), this.Key);
219295

220296
/// <summary>
221297
/// Get Folders for this Library
222298
/// </summary>
223299
/// <returns>List of Folders</returns>
224300
public async Task<object> Folders()
225301
{
226-
return await this.PlexLibraryClient.GetLibraryFolders(this.Server.AccessToken, this.Server.Uri.ToString(),
302+
return await this._plexLibraryClient.GetLibraryFolders(this._server.AccessToken, this._server.Uri.ToString(),
227303
this.Key);
228304
}
229305

230-
/// <summary>
231-
/// Get Filter Type Values
232-
/// </summary>
233-
/// <param name="fieldType">Field Type value (genre, collection, title, etc..)</param>
234-
/// <exception cref="NotImplementedException"></exception>
235-
public async Task<FilterValueContainer> GetFilterValues(string fieldType) =>
236-
await this.PlexLibraryClient.GetLibrarySearchFilters(this.Server.AccessToken, this.Server.Uri.ToString(), this.Key, fieldType);
306+
// /// <summary>
307+
// /// Get Filter Type Values
308+
// /// </summary>
309+
// /// <param name="fieldType">Field Type value (genre, collection, title, etc..)</param>
310+
// /// <exception cref="NotImplementedException"></exception>
311+
// public async Task<FilterValueContainer> GetFilterValues(string fieldType) =>
312+
// await this.PlexLibraryClient.GetLibraryFilterValues(this.Server.AccessToken, this.Server.Uri.ToString(), this.Key, fieldType);
237313
}
238314
}

0 commit comments

Comments
 (0)