diff --git a/PluralKit.API/ApiConfig.cs b/PluralKit.API/ApiConfig.cs index bf7d0ff6..b3946168 100644 --- a/PluralKit.API/ApiConfig.cs +++ b/PluralKit.API/ApiConfig.cs @@ -3,4 +3,6 @@ namespace PluralKit.API; public class ApiConfig { public int Port { get; set; } = 5000; + public string? ClientId { get; set; } + public string? ClientSecret { get; set; } } \ No newline at end of file diff --git a/PluralKit.API/Controllers/PrivateController.cs b/PluralKit.API/Controllers/PrivateController.cs index eebc71a6..c5e0b057 100644 --- a/PluralKit.API/Controllers/PrivateController.cs +++ b/PluralKit.API/Controllers/PrivateController.cs @@ -91,10 +91,74 @@ public class PrivateController: PKControllerBase return NoContent(); } + + [HttpPost("discord/callback")] + public async Task DiscordLogin([FromBody] JObject data) + { + if (_config.ClientId == null) return NotFound(); + + using var client = new HttpClient(); + + var res = await client.PostAsync("https://discord.com/api/v10/oauth2/token", new FormUrlEncodedContent( + new Dictionary{ + { "client_id", _config.ClientId }, + { "client_secret", _config.ClientSecret }, + { "grant_type", "authorization_code" }, + { "redirect_uri", data.Value("redirect_domain") + "/login/discord" }, + { "code", data.Value("code") }, + })); + + var h = await res.Content.ReadAsStringAsync(); + var c = JsonConvert.DeserializeObject(h); + + if (c.access_token == null) + return BadRequest(PrivateJsonExt.ObjectWithError(c.error_description)); + + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {c.access_token}"); + + var resp = await client.GetAsync("https://discord.com/api/v10/users/@me"); + var user = JsonConvert.DeserializeObject(await resp.Content.ReadAsStringAsync()); + var userId = user.Value("id"); + + var system = await ResolveSystem(userId); + if (system == null) + return BadRequest(PrivateJsonExt.ObjectWithError("User does not have a system registered!")); + + // TODO + + // resp = await client.GetAsync("https://discord.com/api/v10/users/@me/guilds"); + // var guilds = JsonConvert.DeserializeObject(await resp.Content.ReadAsStringAsync()); + // await _redis.Connection.GetDatabase().HashSetAsync( + // $"user_guilds::{userId}", + // guilds.Select(g => new HashEntry(g.Value("id"), true)).ToArray() + // ); + + var o = new JObject(); + + o.Add("system", system.ToJson(LookupContext.ByOwner, APIVersion.V2)); + o.Add("user", user); + o.Add("token", system.Token); + + return Ok(o); + } +} + +public record OAuth2TokenResponse +{ + public string access_token; + public string? error; + public string? error_description; } public static class PrivateJsonExt { + public static JObject ObjectWithError(string error) + { + var o = new JObject(); + o.Add("error", error); + return o; + } + public static JArray ToJson(this IEnumerable shards) { var o = new JArray();