Coder Social home page Coder Social logo

plex-api's People

Contributors

anth12 avatar at0dd avatar dependabot[bot] avatar fxsth avatar jasonlandbridge avatar jensenkd avatar lejando avatar mschoneman avatar ombrelin avatar pouleyy avatar sander0542 avatar seertenedos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

plex-api's Issues

track artist (originalTitle instead of grandparentTitle)

Is your feature request related to a problem? Please describe.
the originalTitle field exists for some media while it is null for others, typically it contains the artist of a music track when it is not the same as the album.

Describe the solution you'd like
From what I was able to tell, this api discards this information, would it be possible to make it a nullable field instead?

Describe alternatives you've considered/Additional context
I ended up requesting the session data myself rather than using the api here (between lines 108 and 131). please note that I'm more on a beginner/intermediate skill level when it comes to coding so I did things very unconventionally/incorrect in the app

MetadataKey are strings not ints

When trying to get children data the method wants an int, but the value is a string, Im using the RatingKey. Key is also a string, but doesnt look like the real key.

var metadatas = plexApi.GetChildrenMetadata(string authToken, string plexServerHost, int metadataKey).Result;

image

GetChildrenMetadataAsync returns an empty MediaContainer class

To Reproduce
Steps to reproduce the behavior:

 //SelectedPlexLibrary.PlexServer is Plex.Library.ApiModels.Servers.Server

    async Task Card(Metadata item)
    {
        if (item.Type == "show")
        {
            var seasons = await plexServerClient.GetChildrenMetadataAsync(SelectedPlexLibrary.PlexServer.AccessToken,SelectedPlexLibrary.PlexServer.Uri.ToString(), int.Parse(item.RatingKey));
        }
    }

Expected behavior
To return the correct MediaContainer information

Additional context
I have run the query manually through Postman an as far as I can see it should return the same MediaContainer as other calls.

While I'm at it, is it possible to get a method on Plex.Library.ApiModels.Libraries.ShowLibrary to be able to get Seasons/Episodes of a particular show or season using the rating key?

Not that I'm ungrateful mind you this has saved me hours of work already.

OAuth Example

Do you have an OAuth Example? So users can feel a bit more secure.

ExternalProviderInfo - Doesnt need setter

Can this just be a getter or check for null ;) ?

There is an error when you try to make a class inherit the Metadata class

Newtonsoft.Json.JsonSerializationException: Error setting value to 'ExternalProviderInfo' on 'PlexApps.Dto.PlexShowDto'. System.ArgumentNullException: Value cannot be null. (Parameter 'input')

public string ExternalProviderInfo
    {
      get
      {
        return (string) null;
      }
      set
      {
        Match match = Regex.Match(value, "\\.(?<provider>[a-z]+)://(?<id>[^\\?]+)");
        this.Guid = value;
        this.ExternalProvider = match.Groups["provider"].Value;
        this.ExternalProviderId = match.Groups["id"].Value;
      }
    }

public class PlexShowDto : Metadata
    {
        public List<PlexSeasonDto> PlexSeasons { get; set; }
    }

public class PlexSeasonDto : Metadata
    {
        public List<Metadata> PlexEpisodes { get; set; }
    }

GetUsers not Returning all Users

Describe the bug
PlexAccountClient.GetUsers() does not return all users; it returns all users other than the Home Admin user.

To Reproduce
Steps to reproduce the behavior:

  1. Visit the Home & Library Access page in Server Settings in Plex to see the list of users.
  2. Make a call to PlexAccountClient.GetUsers().
  3. See that the returned users does not include the Home Admin.

Expected behavior
A call to PlexAccountClient.GetUsers() should include all users including the Home Admin.

Additional context
Looking at the implementation of PlexAccountClient.GetUsers() I see that it uses a base URI of https://plex.tv/api/users. I have confirmed that is this base URI is changed to https://plex.tv/api/home/users then all users, including the Home Admin users, are returned as expected.

Is there some reason why we shouldn't hit the /home/users endpoint? Is there any desire to either fix the existing method so that it does hit this endpoint or create an additional one?

DateTime automapping failure when getting server

After successfully logging in, and doing account.Servers() and getting any server from the list, I was met with:
Cannot connect to server: x.x.x.x

Removing the try/catch from Servers(), I was able to get the exception:

Unhandled exception. AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
AccountServer -> Server
Plex.ServerApi.PlexModels.Account.AccountServer -> Plex.Library.ApiModels.Servers.Server

Type Map configuration:
AccountServer -> Server
Plex.ServerApi.PlexModels.Account.AccountServer -> Plex.Library.ApiModels.Servers.Server

Destination Member:
UpdatedAt

 ---> System.FormatException: 03/24/2021 19:32:51 is not a valid value for DateTime.
 ---> System.FormatException: String '03/24/2021 19:32:51' was not recognized as a valid DateTime.
   at System.DateTimeParse.Parse(ReadOnlySpan`1 s, DateTimeFormatInfo dtfi, DateTimeStyles styles)
   at System.DateTime.Parse(String s, IFormatProvider provider)
   at System.ComponentModel.DateTimeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   --- End of inner exception stack trace ---
   at System.ComponentModel.DateTimeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   at System.ComponentModel.TypeConverter.ConvertFrom(Object value)
   at AutoMapper.Mappers.TypeConverterMapper.Map[TSource,TDestination](TSource source)
   at lambda_method2(Closure , AccountServer , Server , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method2(Closure , AccountServer , Server , ResolutionContext )
   at Plex.Library.ApiModels.Servers.Server..ctor(IPlexServerClient plexServerClient, IPlexLibraryClient plexLibraryClient, AccountServer accountServer) in /home/ducky/dev/git/none/plex-cli/lib/plex-api/Source/Plex.Library/ApiModels/Servers/Server.cs:line 41
   at Plex.Library.ApiModels.Accounts.PlexAccount.Servers() in /home/ducky/dev/git/none/plex-cli/lib/plex-api/Source/Plex.Library/ApiModels/Accounts/PlexAccount.cs:line 172
   at PlexCli.Program.Main(String[] args) in /home/ducky/dev/git/none/plex-cli/src/Program.cs:line 49
   at PlexCli.Program.<Main>(String[] args)

Running Plex 1.22.1.4228 on Linux.

Avoid blocking calls in models constructors

Is your feature request related to a problem? Please describe.
I'm developing a client app (using .NET MAUI) using the library, and the blocking calls in the constructor are a pain.

Describe the solution you'd like
I would recommend fecthing the data before constructing the models and then passing the data to map to the constructor

Describe alternatives you've considered
For now I wrap the calls with Task.Run(...) but the overhead and blocking makes the calls very slow.

Metadata - Add Agent Info

Can you add the Agent info on the Meta object. This basically tells what agent was used for the plex match. This way if you have the IMDB or TMDBID you can compare them that way.

guid="com.plexapp.agents.imdb://tt0322259?lang=en"
ExternalProvider = imdb
ExternalProviderId = tt0322259

public string ExternalProvider { get; set; }
        public string ExternalProviderId { get; set; }

        [JsonProperty("guid")]
        public string ExternalProviderInfo
        {
            get => null;
            set
            {
                var match = Regex.Match(value, @"\.(?<provider>[a-z]+)://(?<id>[^\?]+)");
                ExternalProvider = match.Groups["provider"].Value;
                ExternalProviderId = match.Groups["id"].Value;
            }
        }

Automatically failover to LocalAddresses

Is your feature request related to a problem? Please describe.
Can't connect to servers if it has a public IP Address as well as a local, Most Routers don't support Hairpin NAT correctly.

Describe the solution you'd like
Upon failure, if there are LocalIPs listed, then create a URI for each of them and check if you can connect to it.

Describe alternatives you've considered
I've tested it myself by overriding the Host on the AccountServer object, That works and I can continue from here... But obviously auto failover makes sense

Additional context
It's Ugly, but it shows where I've gotten to with it, It just catches the error and then updates the host
image

Get Gessions method not working

Unhandled exception. System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.MediaContainer.Metadata[0].addedAt | LineNumber: 0 | BytePositionInLine: 61.
 ---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.
   at System.Text.Json.Utf8JsonReader.GetString()
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at Plex.ServerApi.Api.ApiService.DeserialiseResponse[T](HttpResponseMessage httpResponse, String contentResponse)
   at Plex.ServerApi.Api.ApiService.InvokeApiAsync[T](ApiRequest request)
   at Plex.ServerApi.Clients.PlexServerClient.FetchWithWrapper[T](String baseUrl, String endpoint, String authToken, HttpMethod method, Dictionary`2 queryParams)
   at Plex.ServerApi.Clients.PlexServerClient.GetSessionsAsync(String authToken, String plexServerHost)

Invite Friend Method Broken

I get a System.NotImplementedException: 'The method or operation is not implemented.' error while using the method myServer.InviteFriend(email, sections);

I took a look at the source and I think (not 100% sure) that the email/username of the invitee is missing as a parameter.

await this.plexServerClient.InviteFriend(this.AccessToken, this.Uri.ToString(), sections, allowSync, allowCameraUpload,

Add Watchlist Functionality

Plex has recently added WatchList as a feature to the server platform.

I'd like to implement the following:

GetWatchlists - Returns list of Movie and Show items that are in a user's watchlist.

IsOnWatchlist - Returns true if the item is on the user's watchlist

AddToWatchlist - Add media item to user's watchlist

RemoveFromWatchlist - Remove media item from user's watchlist

Watchlist capability is stored on Plex.tv and accessible via: 'https://metadata.provider.plex.tv'

JsonException on Subscription@SubscribedAt

Describe the bug
When I try to access an account without a Plex Pass the mapping to the Account fails (The Plex-Token is valid).

To Reproduce
Steps to reproduce the behavior:

var plexAccount = _plexFactory.GetPlexAccount("token-here");

Expected behavior
I get a valid Plex Account without any exceptions

Suggestion
Make the Subscription@SubscribedAt property nullable.

public DateTime SubscribedAt { get; set; }

public DateTime? SubscribedAt { get; set; }

Stack Trace

System.AggregateException: One or more errors occurred. (The JSON value could not be converted to System.DateTime. Path: $.subscription.subscribedAt | LineNumber: 0 | BytePositionInLine: 472.)
 ---> System.Text.Json.JsonException: The JSON value could not be converted to System.DateTime. Path: $.subscription.subscribedAt | LineNumber: 0 | BytePositionInLine: 472.
 ---> System.InvalidOperationException: Cannot get the value of a token type 'Null' as a string.
   at System.Text.Json.Utf8JsonReader.TryGetDateTime(DateTime& value)
   at System.Text.Json.Utf8JsonReader.GetDateTime()
   at System.Text.Json.Serialization.Converters.DateTimeConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
   at Plex.ServerApi.Api.ApiService.DeserialiseResponse[T](HttpResponseMessage httpResponse, String contentResponse)
   at Plex.ServerApi.Api.ApiService.InvokeApiAsync[T](ApiRequest request)
   at Plex.ServerApi.Clients.PlexAccountClient.GetPlexAccountAsync(String authToken)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at Plex.Library.ApiModels.Accounts.PlexAccount..ctor(IPlexAccountClient plexAccountClient, IPlexServerClient plexServerClient, IPlexLibraryClient plexLibraryClient, String authToken)
   at Plex.Library.Factories.PlexFactory.GetPlexAccount(String authToken)
   at Sander0542.Plex.GoogleActions.Web.Controllers.TestController.Index() in C:\GitHub\Sander0542\Sander0542.Plex.GoogleActions\src\Sander0542.Plex.GoogleActions.Web\Controllers\TestController.cs:line 20
   at lambda_method5(Closure , Object )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Versions

  • NET: 6.0
  • C# Lang: 10
  • Plex-Api: 2.0.4 & 2.0.5-preview008

Signing in with Token Throws Exception

When signing in with a token:

var plexFactory = serviceProvider.GetService<IPlexFactory>();
var account = plexFactory.GetPlexAccount(token);

I see an exception thrown, see below. I am running 2.0.0-preview024 and I see that a similar bug had been fixed in that version. I also downgraded to 2.0.0-preview023 but had the same problem. I am running plex v1.23.3.4707 on Linux.

ย  Name Value Type
โ—ข $exception {"Error mapping types.\r\n\r\nMapping types:\r\nPlexAccount -> PlexAccount\r\nPlex.ServerApi.PlexModels.Account.PlexAccount -> Plex.Library.ApiModels.Accounts.PlexAccount\r\n\r\nType Map configuration:\r\nPlexAccount -> PlexAccount\r\nPlex.ServerApi.PlexModels.Account.PlexAccount -> Plex.Library.ApiModels.Accounts.PlexAccount\r\n\r\nDestination Member:\r\nRememberExpiresAt\r\n"} AutoMapper.AutoMapperMappingException
ย  โ–ถ Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
ย  HResult -2146233088 int
ย  HelpLink null string
ย  โ–ถ InnerException {"07/17/2021 14:04:38 is not a valid value for DateTime."} System.Exception {System.FormatException}
ย  โ–ถ MemberMap "RememberExpiresAt" AutoMapper.IMemberMap {AutoMapper.PropertyMap}
ย  Message "Error mapping types.\r\n\r\nMapping types:\r\nPlexAccount -> PlexAccount\r\nPlex.ServerApi.PlexModels.Account.PlexAccount -> Plex.Library.ApiModels.Accounts.PlexAccount\r\n\r\nType Map configuration:\r\nPlexAccount -> PlexAccount\r\nPlex.ServerApi.PlexModels.Account.PlexAccount -> Plex.Library.ApiModels.Accounts.PlexAccount\r\n\r\nDestination Member:\r\nRememberExpiresAt\r\n" string
ย  Source "AutoMapper" string
ย  StackTrace " at lambda_method1(Closure , PlexAccount , PlexAccount , ResolutionContext )\r\n at Plex.Library.ApiModels.Accounts.PlexAccount..ctor(IPlexAccountClient plexAccountClient, IPlexServerClient plexServerClient, IPlexLibraryClient plexLibraryClient, String authToken)\r\n at Plex.Library.Factories.PlexFactory.GetPlexAccount(String authToken)\r\n at TestPlex.Program.Main(String[] args) in C:\Users\justin.elzik\Dropbox\Source\Plex\TestPlex\TestPlex\Program.cs:line 46" string
ย  โ–ถ TargetSite {TDestination MapCore[TSource,TDestination](TSource, TDestination, AutoMapper.ResolutionContext, System.Type, System.Type, AutoMapper.IMemberMap)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
ย  โ–ถ TypeMap "PlexAccount" -> "PlexAccount" AutoMapper.TypeMap
ย  โ–ถ Types "PlexAccount", "PlexAccount" AutoMapper.TypePair?

Add TotalSize property to HistoryMediaContainer

Is your feature request related to a problem? Please describe.

The HistoryMediaContainer does not include a TotalSize property in the same way that the MediaContainer does. This means that when calling IPlexServerClient.GetPlayHistory() it is not possible to know when all the play history has been returned.

Describe the solution you'd like

I'd like to see a TotalSize property added to the HistoryMediaContainer.

Describe alternatives you've considered

You can just keep calling the IPlexServerClient.GetPlayHistory() method with incremented start parameter until the container's HistoryMetadata is returned as null (or size is zero) signifying that even though we don't know the total size, we must have exceeded it. Whilst this works, it is not ideal and an additional HTTP GET is required and wasted. Since the Plex API does return a correctly populated totalSize in its response it would be useful to pass this back.

Delete collection and delete item from collection does not seem to work.

Describe the bug
Deleting collections does not work for me.

To Reproduce

  1. Get a list of collections
  2. foreach one, loop through the items and remove them from the collection
  3. finally delete the collection

Expected behavior
I expected the collections to be deleted. However, after it runs without exceptions, the collections are there, still intact.

Side Note: There is a TODO throw in ApiService line 145 which I had to comment out to get this to function at all.

Here's my code:

var server = factory.CreateServer();
string url = server.Uri.ToString();

try
{
	var libs = await server.Libraries();
	var movies = libs.Single(c => c.Title == "Movies");

	var collections = await factory.PlexLibraryClient.GetCollectionsAsync(server.AccessToken, url, movies.Key, string.Empty);
	foreach (var col in collections.Collections)
	{
		var items = await factory.PlexLibraryClient.GetCollectionItemsAsync(server.AccessToken, url, col.RatingKey);
		foreach (var item in items.Media)
		{
			await factory.PlexLibraryClient.DeleteCollectionFromLibraryItemAsync(server.AccessToken, url, movies.Key, item.RatingKey, col.Title);
		}

		await factory.PlexLibraryClient.DeleteCollectionFromLibraryItemAsync(server.AccessToken, url, movies.Key, col.RatingKey, col.Title);
	}
	
}
catch (Exception ex)
{
	string msg = ex.Message;
}

Can't add specific track to playlist?

Describe the bug
Looking at the API I don't think it's possible to add a specific track to the playlist

For Example when I go into the plex web UI and manually add a track to the playlist I see something like this:

PUT https://myserver:myport/playlists/958874/items?uri=server://myserverid/com.plexapp.plugins.library/library/metadata/917742

If I run this same PUT through powershell it add that specific track to the playlist.
I don't think the API supports this currently or if it does, a repo search of AddPlaylistItems() fails to turn up anything that looks like it can.

account.Servers(); only returns remote servers you can connect to no local ones

Describe the bug
All plex servers have multiple addresses. Normally one remote address and 1+ local addresses that are just IPs an example from my server is "192.168.50.15,192.168.64.1,192.168.128.1,192.168.160.1,192.168.50.16" for the value of LocalAddresses on the account.ServerSummaries() record. Sadly your library never tries to connect using these IP's which should be the fastest and in some cases only access to the server.

To Reproduce
Steps to reproduce the behavior:

  1. Have a server on your local network that can not be accessed by your public IP from your network
  2. run account.Servers();
  3. Notice it could not connect to the server as it only tried the public address.

Expected behavior
I would expect it to connect using local IP's first then the public one if those fail. One thing to be aware of is you may need to disable the HTTPS cert verification when connecting via local IP's

old logic i used.txt
The above attachment is the old code i used to fix this with an older copy of your code that i hope may be helpful

OAuth not working?

I'm not sure if this is me but since the Plex auth outage on the 27th I've not managed to sign in with OAuth again. https://status.plex.tv/

I signed out of Tautulli and back in and that worked, except they are not using the forwardUrl method.

To Reproduce

    [Route("api/[controller]")]
    public class PlexLoginController : Controller
    {
        private readonly OAuthService _oAuthService;
        private readonly IPlexAccountClient _plexClient;

        public PlexLoginController(OAuthService oAuthService, IPlexAccountClient plexClient)
        {
            _oAuthService = oAuthService;
            _plexClient = plexClient;
        }

        [HttpGet]
        public async Task<IActionResult> IndexAsync()
        {
            var returnPath = Request.Scheme + "://" + Request.Host + Request.Path + "/PlexReturn";
            var oauthUrl = await _plexClient.CreateOAuthPinAsync(returnPath);
            _oAuthService.OAuthID = oauthUrl.Id;
            return Redirect(oauthUrl.Url);
        }

        [HttpGet]
        [Route("PlexReturn")]
        public async Task<IActionResult> PlexReturn()
        {
            var oauthId = _oAuthService.OAuthID.ToString();
            var oAuthPin = await _plexClient.GetAuthTokenFromOAuthPinAsync(oauthId);

            if (string.IsNullOrEmpty(oAuthPin.AuthToken))
                throw new Exception("Plex auth failed.");

            _oAuthService.PlexKey = oAuthPin.AuthToken;
            await _oAuthService.Login(oAuthPin.AuthToken);
            return Content(@"<script>window.close();</script>", "text/html");
        }
    }

The Plex login window says "We were unable to complete this request."
image

Expected behavior
To obtain a Plex Authentication Token

Desktop (please complete the following information):

  • OS: Windows
  • Blazor Server
  • Visual Studio 2019 (16.11.3)
  • Plex.Api 2.0.5-preview006

How do we pull album art and such?

Sorry newbie here but I couldnt seem to find any examples or test cases to pull the album and thumbnail artwork down? Is there a simple http I am missing? For music, as of now I have the artist information pulled down with the Art property filled in, but cant seem how to display the image without some bytes or http address.

Thanks much! Btw it was really easy to setup the library and get it running quickly.

EDIT: The easiest way that I have found so far is to rebuild the Art property with an http uri combined with the X-Plex-Token at the end. I didnt know if there is a better way?

EDIT2: Side note, how do we get albums by an artist? I tried using the PlexLibraryClient.LibrarySearch(...) using no title and a filter request with Filter = "artist" and value of the Artist's Metadata.Title but it returns other artist's albums. Addition, I figured I can get them with using a filter on artist.id == Artist.RatingKey. Would the best practice to inherit our own PlexLibraryClient?

Get Collection by Name

I see there is a get collections by key but not by name? Did I miss something like how do I get all movies in the xxx collection or just get collection object by name so it can be updated?

Hidden servers makes account.Servers() crash

Is your feature request related to a problem? Please describe.
My Plex server has two old servers that I cant delete. They dont show up in plex. But I see them in ApiService.
When I run account.Servers() I get all servers in my APIservice. But when Servers() start looping through all the servers to call them, it crashes cause they dont exist.

Describe the solution you'd like
I think it would be nice with a Servers() took in AccountServerContainer so that you could use ServerSummaries() to specifie if you want to exclude servers beeing called.

Describe alternatives you've considered
Maybe take in just a List of either Name of server or IP to exclude severs

Additional context
image
0 and 1 does not exist and makes code crash

image
Calling first and second server

image
The only servers existing in my plex

Access to parent objects on children

With the design of all the method calls coming off the data objects you do not need to access the parent object that created it 90% of the time but i am finding for example that sometime when working at the episode level i need some info from the server or library or account. One option is to just pass those other objects around and that is how i work around it but i beleive a lot of those objects or their info are already in these child objects so it could maybe be exposed.

I work around it anyway so if it is too hard don't worry it was just an idea.
This would be an enhancement not a bug

Revamp Search functionality

Currently when searching, you have to know the key of the values you want to search on.

I want to be able to use filter field text values such as:

genre=Action
actor=Tom Hanks

and I also want to validate that the filter fields and values are correct, else throw known exception.

Instructions on querying the server using a sub user/profile

Is your feature request related to a problem? Please describe.
Unser my user I have a number of accounts for family members that show on the TV screen. I am trying to sync the watch status for different family members between servers and while i can do that for my self as the main user via the API i could not work out how to get the API to use one of the other users under my account to make the calls.

Describe the solution you'd like
Documentation or this issue updated with the steps needed to make calls to the servers from sub user accounts instead of the main user which is default.

Additional context
I am talking about the users you can see on the screen and can set a pin to login as if you want. I can see them in the users collection under my account as well via the API mixed with other users but no idea how to use it when doing further queries as it is all based off the account object returned from login and there did not seem to be a method to select a sub user for the account.

System.FormatException: 09/20/2021 13:04:37 is not a valid value for DateTime.

Describe the bug
I'm getting the same thing as #27 when doing server.Libraries() with 2.0.0-preview025 from Nuget

To Reproduce
Steps to reproduce the behavior: https://github.com/jensenkd/plex-api/blob/master/README.md#library-documentation

  1. I guess use a non US datetime location (UK)?
  2. plexAccount = plexFactory.GetPlexAccount(PlexKey);
  3. plexServers = await plexAccount.Servers();
  4. plexLibraries = await plexServers[0].Libraries();

Expected behavior
Returns a list of Libraries for the server

Desktop (please complete the following information):

  • OS: Windows
  • Browser FireFox
  • Version 2.0.0-preview25

Scrobble/Unscrobble

Mark items as watched

public async Task Scrobble(string ratingKey)
        {
            using (var request = new HttpRequestMessage(HttpMethod.Get,
                "/:/scrobble?identifier=com.plexapp.plugins.library&key=" + ratingKey))
            {
                var resp = await _httpClient.SendAsync(request);
                var respStr = await resp.Content.ReadAsStringAsync();
            }
        }

public async Task Unscrobble(string ratingKey)
        {
            using (var request = new HttpRequestMessage(HttpMethod.Get,
                "/:/unscrobble?identifier=com.plexapp.plugins.library&key=" + ratingKey))
            {
                var resp = await _httpClient.SendAsync(request);
                var respStr = await resp.Content.ReadAsStringAsync();
            }
        }

Playback support?

Hey there, does this support playback control on various devices?

Unable to get server due to plex security setting

Describe the bug
When running the AccountServerContainer.Servers() method, my server only gets returned if the plex > settings > network > secure connections setting is set to "preferred" in stead of "required"

To Reproduce
Steps to reproduce the behavior:

  1. Go to plex > settings > network > secure connections
    image
    And set the secure connection to required:
    image

  2. In your code, run this:

var account = plexFactory.GetPlexAccount(plexToken);

var serversSumm = await account.ServerSummaries(); //always returns 1 server (which is as expected โœ…)
var servers = await account.Servers(); //returns 0 servers when secure connection is required, returns 1 server when "preferred"

Expected behavior
account.Servers() to always return the same amount of servers as ServerSummaries()

Screenshots
image

Additional context
interestingly, within the serverSumm variable that is shown above, there is a property named "Scheme". When inspecting this, I can see that it was set to http, instead of the expected "https" (since the servers security setting is set to require secure connections)
Maybe this plays a role in this story as well.

image

Not able to access LibraryBase.RecentlyAdded() method

Describe the bug

Following the documentation in the README for Libraries will lead you to the following error.

'LibraryBase.RecentlyAdded(SearchType, int, int)' is inaccessible due to its protection level

Was this API changed since this documentation was written?

To Reproduce

Here is an excerpt from my code, this should be cut down enough to show the issue without being too much code I think.

internal async Task Test()
{
    // Login to Plex
    PlexAccount account = _plexFactory.GetPlexAccount(
        "YOUR TOKEN HERE"
    );

    // Only needed if you have more than 1 server owned
    string serverNameToMonitor = "SERVER NAME HERE";

    // Select the available server to check
    List<Server> ownedServers = (await account.Servers()).Where(s => s.Owned == 1).ToList();
    Server monitoredServer = ownedServers.Count switch
    {
        > 1 => ownedServers.First(s => s.FriendlyName == serverNameToMonitor),
        1 => ownedServers.First(),
        _ => throw new UnrecoverableException("You have no owned servers on your Plex account!")
    };

    // Make sure the data we have is up to date
    await monitoredServer.RefreshSync();

    // Check the recently added media in the library
    List<LibraryBase> libraries = await monitoredServer.Libraries();
    foreach (LibraryBase library in libraries)
    {
        MediaContainer recentlyAdded = await library.RecentlyAdded();
    }
}

Expected behavior

I should be able to check the Recently Added for libraries on my server.

Screenshots

image

Desktop (please complete the following information):

  • OS: [e.g. iOS]: Windows 10
  • Browser [e.g. chrome, safari]: Not sure how browser is relevant for this library, but the editor I'm using is Visual Studio 2022.
  • Version [e.g. 22]: Nuget package Plex.Api version 2.0.4

Additional context

If I'm really not sure if I'm doing something wrong here or if the documentation is wrong, but either way I thought of opening an issue to check on this. Thank you in advance for your time!

Plex.Api.sln missing projects

Describe the bug
Not necessarily a bug, but missing folders and files from project download. After I Git Clone and open the Plex.Api.sln in Visual Studio 2019, I get the following errors and warnings.

Severity	Code	Description	Project	File	Line	Suppression State
Error	NU1104	Unable to find project 'C:\GitProjects\plex-api\Source\Plex.Api\Plex.Api.csproj'. Check that the project reference is valid and that the project file exists.	Plex.Library.Test	C:\GitProjects\plex-api\Tests\Plex.Library.Test\Plex.Library.Test.csproj	1
Error	NU1104	Unable to find project 'C:\GitProjects\plex-api\Source\Plex.Api\Plex.Api.csproj'. Check that the project reference is valid and that the project file exists.	Plex.ServerApi.Test	C:\GitProjects\plex-api\Tests\Plex.ServerApi.Test\Plex.ServerApi.Test.csproj	1	
Warning		The referenced project '..\..\Source\Plex.Api\Plex.Api.csproj' does not exist.	Plex.Library.Test	C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets	1966	
Warning		The referenced project '..\..\Source\Plex.Api\Plex.Api.csproj' does not exist.	Plex.ServerApi.Test	C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets	1966	

There doesn't appear to be a Plex.Api folder in the Source folder.

To Reproduce
Steps to reproduce the behavior:

  1. Clone the project to your computer, https://github.com/jensenkd/plex-api.git
  2. Go into the resulting plex-api folder.
  3. Double-click on the Plex.Api.sln solution file to open it in Visual Studio. In my case, Visual Studio 2019
  4. See error and warning messages in Output

Expected behavior
I expected there would be no missing folders and files or information in the README.md that would explain the need to download additional files.

Screenshots
Not necessary.

Desktop (please complete the following information):

  • OS: Windows 10 20H2
  • Visual Studio 2019
  • .NET SDK 5.0.301
  • .NET runtimes installed:
    Microsoft.AspNetCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.AspNetCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
    Microsoft.NETCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.NETCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
    Microsoft.WindowsDesktop.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    Microsoft.WindowsDesktop.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Smartphone (please complete the following information):

  • Device: N/A
  • OS: N/A
  • Browser N/A
  • Version N/A

Additional context
Basically, I am trying to follow the README.md for my own project and getting lots of error messages with the following piece of code:

// Create Client Options
    var apiOptions = new ClientOptions
    {
        Product = "API_UnitTests",
        DeviceName = "API_UnitTests",
        ClientId = "MyClientId",
        Platform = "Web",
        Version = "v1"
    };

    // Setup Dependency Injection
    var services = new ServiceCollection();
    services.AddSingleton(apiOptions);
    services.AddTransient<IPlexServerClient, PlexServerClient>();
    services.AddTransient<IPlexAccountClient, PlexAccountClient>();
    services.AddTransient<IPlexLibraryClient, PlexLibraryClient>();
    services.AddTransient<IApiService, ApiService>();
    services.AddTransient<IPlexFactory, PlexFactory>();
    services.AddTransient<IPlexRequestsHttpClient, PlexRequestsHttpClient>();
    
    this.ServiceProvider = services.BuildServiceProvider();

I have found that I can resolve the error messages for "The type or namespace 'xxxxxxx' could not be found..." for the following items by adding the code below.

  • ClientOptions
  • ServiceCollection
  • PlexAccount
using Microsoft.Extensions.DependencyInjection;
using Plex.Api;
using Plex.Api.Models;

However, I am still new to C# and Microsoft's Dependency Injection and not sure how to resolve the other missing namespaces for ServiceProvider and all of the IPlex.... items.

So, I was hoping to open the Plex.Api.sln solution and look at the different projects to find out what I am missing. Honestly, it would be great and save me lots of hours if the required information was in the README.md file and not just assume everyone knows what to include to make the code work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.