mirror of
https://github.com/LukeHagar/plexcsharp.git
synced 2025-12-07 04:20:48 +00:00
## Csharp SDK Changes:
* `PlexApi.LibraryPlaylists.AddPlaylistItems()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryPlaylists.ClearPlaylistItems()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryCollections.MoveCollectionItem()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryCollections.DeleteCollectionItem()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryCollections.AddCollectionItems()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Content.GetSonicallySimilar()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Butler.StopTask()`: `request` **Changed** **Breaking** ⚠️ * `PlexApi.Butler.StartTask()`: `request` **Changed** **Breaking** ⚠️ * `PlexApi.Content.GetSonicPath()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.DownloadQueue.GetItemDecision()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetAllHubs()`: * `request.OnlyTransient` **Changed** * `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetContinueWatching()`: `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetPromotedHubs()`: `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetMetadataHubs()`: * `request.OnlyTransient` **Changed** * `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetPostplayHubs()`: * `request.OnlyTransient` **Changed** * `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetRelatedHubs()`: * `request.OnlyTransient` **Changed** * `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Hubs.GetSectionHubs()`: * `request.OnlyTransient` **Changed** * `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Content.GetAllLeaves()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Content.ListContent()`: * `request` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Search.SearchHubs()`: `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Content.GetAlbums()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetLibraryItems()`: * `request.MediaQuery` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.IngestTransientItem()`: * `request` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetLibraryMatches()`: * `request` **Changed** **Breaking** ⚠️ * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Content.GetMetadataItem()`: * `request` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetSections()`: `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.AddSection()`: * `request` **Changed** * `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetTags()`: * `request.Type` **Changed** **Breaking** ⚠️ * `PlexApi.Content.GetCollectionItems()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetAllItemLeaves()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Status.ListSessions()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.MovePlayQueueItem()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetExtras()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.DeletePlayQueueItem()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.Unshuffle()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.ListMatches()`: * `request.Manual` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.ListSonicallySimilar()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.Shuffle()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetRelatedItems()`: `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.ListSimilar()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.ResetPlayQueue()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetItemTree()`: `response.mediaContainer.MetadataItem.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.ClearPlayQueue()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.AddToPlayQueue()`: * `request.Next` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetCommon()`: * `request.MediaQuery` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetPerson()`: `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.ListPersonMedia()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.PlayQueue.GetPlayQueue()`: * `request` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetLibraryDetails()`: * `request.IncludeDetails` **Changed** * `response.mediaContainer.Directory.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryPlaylists.MovePlaylistItem()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.Autocomplete()`: * `request.MediaQuery` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Library.GetCollections()`: * `request.MediaQuery` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryPlaylists.GetPlaylistGeneratorItems()`: `response.mediaContainer.Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryPlaylists.DeletePlaylistItem()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Search.VoiceSearchHubs()`: * `request.Type` **Changed** **Breaking** ⚠️ * `response.mediaContainer.Hub.[].Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LibraryPlaylists.CreatePlaylist()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Playlist.GetPlaylistItems()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Playlist.GetPlaylist()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Playlist.ListPlaylists()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Collections.CreateCollection()`: * `request.Type` **Changed** **Breaking** ⚠️ * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.DvRs.TuneChannel()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LiveTv.GetSessions()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.LiveTv.GetLiveTvSession()`: `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Transcoder.MakeDecision()`: * `request` **Changed** * `response.mediaContainer.Metadata.[]` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.GetAllSubscriptions()`: * `request` **Changed** * `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.CreateSubscription()`: `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.GetScheduledRecordings()`: `response.mediaContainer.MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.GetTemplate()`: `response.mediaContainer.SubscriptionTemplate.[].MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.GetSubscription()`: * `request` **Changed** * `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.EditSubscriptionPreferences()`: `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Subscriptions.ReorderSubscription()`: `response.mediaContainer.MediaSubscription.[].MediaGrabOperation.[].Metadata` **Changed** **Breaking** ⚠️ * `PlexApi.Library.AddSubtitles()`: `request` **Changed** * `PlexApi.LibraryPlaylists.UploadPlaylist()`: * `request.Force` **Changed** * `PlexApi.Transcoder.TranscodeSubtitles()`: `request` **Changed** * `PlexApi.Transcoder.StartTranscodeSession()`: `request` **Changed** * `PlexApi.Library.GetMediaPart()`: * `request.Download` **Changed** * `PlexApi.Library.DetectIntros()`: * `request.Force` **Changed** * `PlexApi.Library.GetSectionImage()`: * `request.MediaQuery` **Changed** * `PlexApi.Library.DeleteMediaItem()`: * `request.Proxy` **Changed** * `PlexApi.Library.RefreshItemsMetadata()`: * `request.MarkUpdated` **Changed** * `PlexApi.Authentication.Post-Users-Sign-In-Data()`: **Added** * `PlexApi.Authentication.GetTokenDetails()`: **Added** * `PlexApi.Library.DetectCredits()`: `request` **Changed** * `PlexApi.Library.SetStreamSelection()`: * `request.AllParts` **Changed** * `PlexApi.Library.UpdateItems()`: * `request.Field.locked` **Changed** * `PlexApi.PlayQueue.CreatePlayQueue()`: `request` **Changed** * `PlexApi.Library.DeleteLibrarySection()`: * `request.Async` **Changed** * `PlexApi.Library.GetAugmentationStatus()`: * `request.Wait` **Changed** * `PlexApi.Transcoder.TranscodeImage()`: `request` **Changed** * `PlexApi.Devices.ModifyDevice()`: * `request.Enabled` **Changed** * `PlexApi.Library.DetectVoiceActivity()`: `request` **Changed** * `PlexApi.Library.GetStream()`: * `request.AutoAdjustSubtitle` **Changed** * `PlexApi.Library.StartBifGeneration()`: * `request.Force` **Changed** * `PlexApi.Library.GetFirstCharacters()`: * `request.MediaQuery` **Changed** * `PlexApi.UltraBlur.GetImage()`: * `request.Noise` **Changed** * `PlexApi.Library.GenerateThumbs()`: * `request.Force` **Changed** * `PlexApi.Updater.ApplyUpdates()`: `request` **Changed** * `PlexApi.Updater.CheckUpdates()`: * `request.Download` **Changed** * `PlexApi.Library.DeleteMetadataItem()`: * `request.Proxy` **Changed** * `PlexApi.Library.OptimizeDatabase()`: * `request.Async` **Changed** * `PlexApi.Library.RefreshSection()`: * `request.Force` **Changed** * `PlexApi.Hubs.UpdateHubVisibility()`: `request` **Changed** * `PlexApi.Hubs.CreateCustomHub()`: `request` **Changed** * `PlexApi.DownloadQueue.AddDownloadQueueItems()`: `request` **Changed** * `PlexApi.Timeline.Report()`: `request` **Changed** * `PlexApi.General.GetSourceConnectionInformation()`: * `request.Refresh` **Changed** * `PlexApi.Plex.Get-Server-Resources()`: **Added** * `PlexApi.Users.Get-Users()`: **Added**
This commit is contained in:
@@ -17,7 +17,7 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
|
||||
internal static class URLBuilder
|
||||
{
|
||||
public static string Build(string baseUrl, string relativeUrl, object? request)
|
||||
public static string Build(string baseUrl, string relativeUrl, object? request, List<string>? allowEmptyValue = null)
|
||||
{
|
||||
var url = baseUrl;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
var parameters = GetPathParameters(request);
|
||||
url = ReplaceParameters(url, parameters);
|
||||
|
||||
var queryParams = SerializeQueryParams(TrySerializeQueryParams(request));
|
||||
var queryParams = SerializeQueryParams(TrySerializeQueryParams(request, allowEmptyValue));
|
||||
if (queryParams != "")
|
||||
{
|
||||
url += $"?{queryParams}";
|
||||
@@ -90,10 +90,6 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
{
|
||||
var val = prop.GetValue(request);
|
||||
|
||||
if (val == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetRequestMetadata() != null)
|
||||
{
|
||||
@@ -107,6 +103,13 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle null values and empty arrays as empty query parameters
|
||||
if (val == null || (Utilities.IsList(val) && ((IList)val).Count == 0))
|
||||
{
|
||||
parameters.Add(metadata.Name ?? prop.Name, "");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (metadata.Serialization != null)
|
||||
{
|
||||
switch (metadata.Serialization)
|
||||
@@ -147,7 +150,7 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private static Dictionary<string, List<string>> TrySerializeQueryParams(object? request)
|
||||
private static Dictionary<string, List<string>> TrySerializeQueryParams(object? request, List<string>? allowEmptyValue = null)
|
||||
{
|
||||
var parameters = new Dictionary<string, List<string>>();
|
||||
|
||||
@@ -161,9 +164,20 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
foreach (var prop in props)
|
||||
{
|
||||
var val = prop.GetValue(request);
|
||||
|
||||
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetQueryParamMetadata();
|
||||
|
||||
if (val == null)
|
||||
{
|
||||
// If this parameter is in allowEmptyValue and val is null, include it as empty
|
||||
if (metadata != null && allowEmptyValue?.Contains(metadata.Name ?? prop.Name) == true)
|
||||
{
|
||||
var paramName = metadata.Name ?? prop.Name;
|
||||
if (!parameters.ContainsKey(paramName))
|
||||
{
|
||||
parameters.Add(paramName, new List<string>());
|
||||
}
|
||||
parameters[paramName].Add("");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -172,7 +186,6 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
continue;
|
||||
}
|
||||
|
||||
var metadata = prop.GetCustomAttribute<SpeakeasyMetadata>()?.GetQueryParamMetadata();
|
||||
if (metadata == null)
|
||||
{
|
||||
continue;
|
||||
@@ -207,7 +220,8 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
metadata.Name ?? prop.Name,
|
||||
val,
|
||||
metadata.Explode,
|
||||
","
|
||||
",",
|
||||
allowEmptyValue
|
||||
);
|
||||
foreach (var key in formParams.Keys)
|
||||
{
|
||||
@@ -245,7 +259,8 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
metadata.Name ?? prop.Name,
|
||||
val,
|
||||
metadata.Explode,
|
||||
"|"
|
||||
"|",
|
||||
allowEmptyValue
|
||||
);
|
||||
foreach (var key in pipeParams.Keys)
|
||||
{
|
||||
@@ -358,7 +373,8 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
string parentName,
|
||||
object value,
|
||||
bool explode,
|
||||
string delimiter
|
||||
string delimiter,
|
||||
List<string>? allowEmptyValue = null
|
||||
)
|
||||
{
|
||||
var parameters = new Dictionary<string, List<string>>();
|
||||
@@ -458,32 +474,45 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
{
|
||||
var values = new List<string>();
|
||||
var items = new List<string>();
|
||||
var list = (IList)value;
|
||||
|
||||
foreach (var item in (IList)value)
|
||||
{
|
||||
if (explode)
|
||||
{
|
||||
values.Add(Utilities.ValueToString(item));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(Utilities.ValueToString(item));
|
||||
}
|
||||
}
|
||||
|
||||
if (items.Count > 0)
|
||||
{
|
||||
values.Add(string.Join(delimiter, items));
|
||||
}
|
||||
|
||||
foreach (var val in values)
|
||||
// Handle empty arrays - add empty parameter if allowEmptyValue includes this parameter
|
||||
if (list.Count == 0 && allowEmptyValue?.Contains(parentName) == true)
|
||||
{
|
||||
if (!parameters.ContainsKey(parentName))
|
||||
{
|
||||
parameters.Add(parentName, new List<string>());
|
||||
}
|
||||
parameters[parentName].Add("");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (explode)
|
||||
{
|
||||
values.Add(Utilities.ValueToString(item));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(Utilities.ValueToString(item));
|
||||
}
|
||||
}
|
||||
|
||||
parameters[parentName].Add(val);
|
||||
if (items.Count > 0)
|
||||
{
|
||||
values.Add(string.Join(delimiter, items));
|
||||
}
|
||||
|
||||
foreach (var val in values)
|
||||
{
|
||||
if (!parameters.ContainsKey(parentName))
|
||||
{
|
||||
parameters.Add(parentName, new List<string>());
|
||||
}
|
||||
|
||||
parameters[parentName].Add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -493,7 +522,16 @@ namespace LukeHagar.PlexAPI.SDK.Utils
|
||||
parameters.Add(parentName, new List<string>());
|
||||
}
|
||||
|
||||
parameters[parentName].Add(Utilities.ValueToString(value));
|
||||
// Handle null values and empty strings for allowEmptyValue parameters
|
||||
var stringValue = Utilities.ValueToString(value);
|
||||
if ((value == null || stringValue == "") && allowEmptyValue?.Contains(parentName) == true)
|
||||
{
|
||||
parameters[parentName].Add("");
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters[parentName].Add(stringValue);
|
||||
}
|
||||
}
|
||||
|
||||
return parameters;
|
||||
|
||||
Reference in New Issue
Block a user