Skip to content

Commit

Permalink
Overhauled Plex.tv login
Browse files Browse the repository at this point in the history
  • Loading branch information
Brhsoftco committed Jul 3, 2020
1 parent 81b0f8e commit 1e8e88e
Show file tree
Hide file tree
Showing 25 changed files with 1,725 additions and 3,142 deletions.
3,459 changes: 857 additions & 2,602 deletions PlexDL.Installer/PlexDL.Installer.vdproj

Large diffs are not rendered by default.

146 changes: 146 additions & 0 deletions PlexDL.PlexAPI.LoginHandler/Auth/PlexPins.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using PlexDL.PlexAPI.Auth;
//
// var plexPins = PlexPins.FromJson(jsonString);

namespace PlexDL.PlexAPI.LoginHandler.Auth
{
using System;

using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using UIHelpers;

public partial class PlexPins
{
public static PlexPins NewPlexAuthPin()
{
var j = Get.DownloadJson(Endpoints.PlexPinsEndpoint,RestSharp.Method.POST);
return FromJson(j);
}
public PlexPins FromPinEndpoint()
{
var j = Get.DownloadJson(PinEndpointUrl);
return FromJson(j);
}

public string PinEndpointUrl => $"https://plex.tv/api/v2/pins/{Id}";
public string LoginInterfaceUrl => $"https://app.plex.tv/auth/#!?clientID={PlexDefs.ClientID}&context[device][version]=Plex OAuth&context[device][model]=Plex OAuth&code={Code}&context[device][product]=Plex Web";

[JsonProperty("id")]
public long Id { get; set; }

[JsonProperty("code")]
public string Code { get; set; }

[JsonProperty("product")]
public string Product { get; set; }

[JsonProperty("trusted")]
public bool Trusted { get; set; }

[JsonProperty("clientIdentifier")]
public string ClientIdentifier { get; set; }

[JsonProperty("location")]
public Location Location { get; set; }

[JsonProperty("expiresIn")]
public long ExpiresIn { get; set; }

[JsonProperty("createdAt")]
public DateTimeOffset CreatedAt { get; set; }

[JsonProperty("expiresAt")]
public DateTimeOffset ExpiresAt { get; set; }

[JsonProperty("authToken")]
public string AuthToken { get; set; }

[JsonProperty("newRegistration")]
public object NewRegistration { get; set; }
}

public partial class Location
{
[JsonProperty("code")]
public string Code { get; set; }

[JsonProperty("country")]
public string Country { get; set; }

[JsonProperty("city")]
public string City { get; set; }

[JsonProperty("time_zone")]
public string TimeZone { get; set; }

[JsonProperty("postal_code")]
[JsonConverter(typeof(ParseStringConverter))]
public long PostalCode { get; set; }

[JsonProperty("subdivisions")]
public string Subdivisions { get; set; }

[JsonProperty("coordinates")]
public string Coordinates { get; set; }
}

public partial class PlexPins
{
public static PlexPins FromJson(string json) => JsonConvert.DeserializeObject<PlexPins>(json, Converter.Settings);
}

public static class Serialize
{
public static string ToJson(this PlexPins self) => JsonConvert.SerializeObject(self, Converter.Settings);
}

internal static class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}

internal class ParseStringConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);

public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
var value = serializer.Deserialize<string>(reader);
long l;
if (Int64.TryParse(value, out l))
{
return l;
}
throw new Exception("Cannot unmarshal type long");
}

public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
if (untypedValue == null)
{
serializer.Serialize(writer, null);
return;
}
var value = (long)untypedValue;
serializer.Serialize(writer, value.ToString());
return;
}

public static readonly ParseStringConverter Singleton = new ParseStringConverter();
}
}
55 changes: 55 additions & 0 deletions PlexDL.PlexAPI.LoginHandler/AuthRoutine.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using PlexDL.PlexAPI.LoginHandler.Auth;
using PlexDL.WaitWindow;
using System.Windows.Forms;

namespace PlexDL.PlexAPI.LoginHandler
{
public static class AuthRoutine
{
public static string GetAuthToken()
{
var stored = TokenManager.StoredToken();

if (string.IsNullOrEmpty(stored))
{
//request a new Auth ticket
var init = NewInit();

using (var frm = new LoginWindow())
{
frm.PlexRequestPin = init;
if (frm.ShowDialog() == DialogResult.OK)
{
if (frm.Success)
{
if (frm.Result != null)
{
var t = frm.Result.AuthToken;
TokenManager.SaveToken(t);
return t;
}
else
return null;
}
else
return null;
}
else
return null;
}
}
else
return stored;
}

private static PlexPins NewInit()
{
return (PlexPins)WaitWindow.WaitWindow.Show(NewInit_Callback, @"Talking to Plex.tv");
}

private static void NewInit_Callback(object sender, WaitWindowEventArgs e)
{
e.Result = PlexPins.NewPlexAuthPin();
}
}
}
7 changes: 7 additions & 0 deletions PlexDL.PlexAPI.LoginHandler/Endpoints.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace PlexDL.PlexAPI.LoginHandler
{
public static class Endpoints
{
public static string PlexPinsEndpoint { get; set; } = @"https://plex.tv/api/v2/pins?strong=true";
}
}
24 changes: 24 additions & 0 deletions PlexDL.PlexAPI.LoginHandler/Get.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using PlexDL.PlexAPI.LoginHandler;
using RestSharp;

namespace PlexDL.PlexAPI.LoginHandler
{
public static class Get
{
public static string DownloadJson(string url, Method method = Method.GET)
{
var client = new RestClient(url);
client.Timeout = -1;
var request = new RestRequest(method);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-Plex-Product", PlexDefs.Product);
request.AddHeader("X-Plex-Version", PlexDefs.Version);
request.AddHeader("X-Plex-Client-Identifier", PlexDefs.ClientID);
request.AddHeader("X-Plex-Model", PlexDefs.Model);
IRestResponse response = client.Execute(request);

// if string with JSON data is not empty, deserialize it to class and return its instance
return !string.IsNullOrEmpty(response.Content) ? response.Content : string.Empty;
}
}
}
130 changes: 130 additions & 0 deletions PlexDL.PlexAPI.LoginHandler/LoginWindow.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1e8e88e

Please sign in to comment.