plex-api icon indicating copy to clipboard operation
plex-api copied to clipboard

Automatically failover to LocalAddresses

Open Biztactix-Ryan opened this issue 2 years ago • 3 comments

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

Biztactix-Ryan avatar Feb 25 '23 04:02 Biztactix-Ryan

Ran into the exact same problem and used your code verbatim.. problem solved! Thanks, saved me so much time.

Still Ugly but maybe less ugly extension method:

MyServer = services.ConnectToPlexServer(key, servername);
Extension Method


using Microsoft.Extensions.DependencyInjection;
using Plex.Api.Factories;
using Plex.Library.ApiModels.Servers;
using Plex.ServerApi.Clients.Interfaces;
using Plex.ServerApi.PlexModels.Account;


namespace PlexMakePlaylist
{
    public static class PlexExtensions
    {
        public static Server? ConnectToPlexServer(this IServiceProvider services, string token, string serverName = "", bool TryLocalFirst = true, bool OwnedOnly = true)
        {
            Server? myserver = null;
            var _plexFactory = services.GetService<IPlexFactory>();
            Plex.ServerApi.PlexModels.Server.PlexServer? server = null;
            if (_plexFactory != null)
            {
                var account = _plexFactory
                    .GetPlexAccount(token);
                var serversum = account.ServerSummaries().Result;
                var server1 = serversum.Servers
                    .Where(x =>
                        (x.Owned == 1 || OwnedOnly == false) &&
                        (x.Name == serverName || serverName == "")
                    )
                    .First();
                var serverClient = services.GetService<IPlexServerClient>();
                if (serverClient == null) throw new MissingMemberException("Missing IPlexServerClient Service");
                var libClient = services.GetService<IPlexLibraryClient>();
                if (libClient == null) throw new MissingMemberException("Missing IPlexLibraryClient Service");

                if (TryLocalFirst)
                {                    
                    myserver = ConnectLocal(server1, serverClient, libClient);
                    if (myserver == null) myserver=ConnectRemote(server1, serverClient, libClient);
                }
                else
                {
                    myserver = ConnectRemote(server1, serverClient, libClient);
                    if (myserver == null) myserver = ConnectLocal(server1, serverClient, libClient);
                }
            }
            return myserver;
        }

        private static Server? ConnectLocal(AccountServer server1, IPlexServerClient? serverClient, IPlexLibraryClient? libClient)
        {
            Server? myserver = null;
            try
            {
                List<string> localIP = new List<string>();
                if (!server1.LocalAddresses.Contains(","))
                    localIP.Add(server1.LocalAddresses);
                else
                    localIP.AddRange(server1.LocalAddresses.Split(","));

                foreach (string ip in localIP)
                {
                    server1.Host = ip;
                    myserver = new Server(serverClient, libClient, server1);
                    break; // assume if this went OK we are connected
                }
            }
            catch 
            { 
                // TODO: don't rely on exception for this somehow?                  
            }

            return myserver;
        }

        private static Server? ConnectRemote(AccountServer server1, IPlexServerClient serverClient, IPlexLibraryClient? libClient)
        {
            Server? myserver = null;
            try
            {
                myserver = new Server(serverClient, libClient, server1);
            }
            catch
            {
                // TODO: don't rely on exception for this somehow?                  
            }

            return myserver;
        }
    }
}

Tailslide avatar Mar 21 '23 15:03 Tailslide

I'll try to take a look at this this weekend.

jensenkd avatar Mar 22 '23 13:03 jensenkd

Ran into the exact same problem and used your code verbatim.. problem solved! Thanks, saved me so much time.

Still Ugly but maybe less ugly extension method:

MyServer = services.ConnectToPlexServer(key, servername);

Thanks... Your code is much nicer, I wasn't particularly in the mood for nice by that point, the plex bit was supposed to be the easy part ;) The old, I'll just write a quick bit of code to pull a list of all the shows I watch on Plex... and why isn't that working....

Biztactix-Ryan avatar Mar 22 '23 23:03 Biztactix-Ryan