jensenkd / plex-api

.NET Core SDK for Plex Media Server
MIT License
86 stars 27 forks source link

GetServers Not Returning All Servers #7

Closed bbakermmc closed 4 years ago

bbakermmc commented 4 years ago

It looks like the GetServers isnt working correctly. I can only see 1 server (my local). But I have multiple.

bbakermmc commented 4 years ago

Im doing a blazor project, and Im just awaiting the call, I get the first record, if I use the .Results the project just hangs trying to pull records.

@page "/plex"
@using Microsoft.AspNetCore.Http
@using PlexApps.Plex
@using global::Plex.Api
@using global::Plex.Api.Models.Server

@inject PlexOAuthClient PlexOAuthClient
@inject IHttpContextAccessor HttpContextAccessor
@inject IPlexClient PlexClient

<h1>Plex</h1>

@if (Servers == null)
{
    <p>
        <em>Loading...</em>
    </p>
}
else
{
    <table class="table">
        <thead>
        <tr>
            <th>Name</th>
            <th>Version</th>
            <th></th>
        </tr>
        </thead>
        <tbody>
        @foreach (var server in Servers)
        {
            <tr>
                <td>@server.Name</td>
                <td>@server.Version</td>
                @{
                    string link = $"/libraries/{server.MachineIdentifier}"; 
            } 
                <td><NavLink href="@link">Set Server</NavLink></td>
            </tr>
        }
        </tbody>
    </table>
}

@code {
    private List<Server> Servers { get; set; }

    protected override async Task OnInitializedAsync()
    {
        var plexKey = HttpContextAccessor.HttpContext.Session.GetString("PlexKey");
        Servers = await PlexClient.GetServers(plexKey);
    }
}
jensenkd commented 4 years ago

I haven't tried Blazer yet, but I'll see if I can scaffold a quick project to test it.

If you use the access token for a single server, it will return only that server. You need to use the access token from your plex login (which is different).

bbakermmc commented 4 years ago

If I use the test project and just pass over my token. Still only 1 result. Have you tried with multiple? It seems like most of your endpoints don’t return multiple things.

bbakermmc commented 4 years ago

Here is the server calls from the trakt to plex solution and it works fine.

public async Task<Server[]> GetServers()
        {
            var servers = new List<Server>();
            using (var request = new HttpRequestMessage(HttpMethod.Get, "https://plex.tv/api/resources"))
            {
                var resp = await _httpClient.SendAsync(request);
                var respStr = await resp.Content.ReadAsStringAsync();
                var xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(respStr);
                var container = xmlDoc.ChildNodes.OfType<XmlNode>().FirstOrDefault(x => x.Name == "MediaContainer");
                if (container == null)
                    return new Server[0];
                foreach (var serverNode in container.ChildNodes.OfType<XmlNode>().Where(x => x.Attributes["product"].Value == "Plex Media Server" && x.ChildNodes.OfType<XmlNode>().Any(y => y.Attributes["local"].Value == "0")))
                {
                    servers.Add(new Server
                    {
                        Name = serverNode.Attributes["name"].Value,
                        Id = serverNode.Attributes["clientIdentifier"].Value,
                        Url = serverNode.ChildNodes.OfType<XmlNode>().First(x => x.Attributes["local"].Value == "0").Attributes["uri"].Value
                    });
                }

                return servers.ToArray();
            }
bbakermmc commented 4 years ago

@jensenkd Just to confirm. Using the API-Test Test_SignIn, I take the access token from the User object on that test, and then use it in the Test_Get_Server and I only get 1 server. Iver never seen different types of access keys before for Plex. All the python scripts work the same.

jensenkd commented 4 years ago

take a look at the test Test_Get_Account()

This will give you a plex account Authentication Token. I believe Signin is for manipulating your account on Plex.tv.

bbakermmc commented 4 years ago

Like I said, pretty sure plex only has 1 key. There is no diff.

I have a key using my old oauth code, that key is saved into session as you can see, then I call your method to get the account, I take that key pass it to the servers as you can see the key the same even after I call get account, and servers still only returns 1.

image

jensenkd commented 4 years ago

It's weird..there is no scenario where I don't get 2 servers.

I mean the code is very simple..it's really just returning the xml response from this: https://plex.tv/pms/servers.xml?X-Plex-Token=YOUR_TOKEN_HERE

If you put your token in that link, you're getting both servers?

bbakermmc commented 4 years ago

I’ll try tonight but pretty sure I only got one.

bbakermmc commented 4 years ago

The server that shows up is my locally hosted sever but not the one remotely hosted

bbakermmc commented 4 years ago

@jensenkd Confirming that servers.xml does not show me two servers.

My admin does. image

bbakermmc commented 4 years ago

Looks like its pulling it from here: https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1&X-Plex-Product=Plex%20Web&X-Plex-Version=4.34.2&X-Plex-Client-Identifier=i8r7syej5lhb5gxnwmq1vzhv&X-Plex-Platform=Firefox&X-Plex-Platform-Version=76.0&X-Plex-Sync-Version=2&X-Plex-Features=external-media%2Cindirect-media&X-Plex-Model=hosted&X-Plex-Device=Windows&X-Plex-Device-Name=Firefox&X-Plex-Device-Screen-Resolution=1920x771%2C1920x1200&X-Plex-Token=TOKENME&X-Plex-Language=en

or

https://plex.tv/devices.xml?X-Plex-Product=Plex%20Web&X-Plex-Version=4.34.2&X-Plex-Client-Identifier=i8r7syej5lhb5gxnwmq1vzhv&X-Plex-Platform=Firefox&X-Plex-Platform-Version=76.0&X-Plex-Sync-Version=2&X-Plex-Features=external-media%2Cindirect-media&X-Plex-Model=hosted&X-Plex-Device=Windows&X-Plex-Device-Name=Firefox&X-Plex-Device-Screen-Resolution=1920x771%2C1920x1200&X-Plex-Token=TOKENME&X-Plex-Language=en

bbakermmc commented 4 years ago

@jensenkd Can you make a devices endpoint, I can use that instead. I'm just trying to use this api though, so as soon as you can give me a list of servers I can get further with what Im trying to do :)

jensenkd commented 4 years ago

1.0.92

[TestMethod]
public void Test_Get_Resources()
{
      var plexApi = ServiceProvider.GetService<IPlexClient>();
      var authKey = Configuration.GetValue<string>("Plex:AuthenticationKey");
      var resources = plexApi.GetResources(authKey).Result;
      Assert.IsNotNull(resources);
}
bbakermmc commented 4 years ago

@jensenkd Looks good for me. This is what I did:

On my prev page, I have user select the server, pass that clientId over, then re lookup the stuff. But you need to pull the URI from the connections Id assume you want HTTPS and non locals ;) You can then pass that URI to the other methods that take the URL and it works perfect. Ill let you know if I need something else lol. Some of the properties could be changed from string to bool if you looked at the data sets, basically all the 1/0 options but thats minor.

 var plexKey = HttpContextAccessor.HttpContext.Session.GetString("PlexKey");
        var servers = await PlexClient.GetResources(plexKey);
        var serverUrl = ((servers.SingleOrDefault(x => x.ClientIdentifier == Server)?.Connections) ?? throw new InvalidOperationException()).FirstOrDefault(y => y.Protocol == "https" && y.Local == "0")?.Uri;
        Libs = await PlexClient.GetLibraries(plexKey, serverUrl);
jensenkd commented 4 years ago

@bbakermmc looks good. Yes I have a task to look at all the types. https://github.com/jensenkd/plex-api/issues/5

The Plex Api is crap and is inconsistent in their types across different endpoints. We're probably safe with the Resource model since they are not returned from any other endpoints that I can tell.