188 lines
7.3 KiB
C#
188 lines
7.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Threading.Tasks;
|
|
using ChaosBot.ConfigHelpers;
|
|
using ChaosBot.Discord;
|
|
using ChaosBot.WebServer.Services;
|
|
using Discord;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace ChaosBot.WebServer.App
|
|
{
|
|
[ApiController]
|
|
[Route("/api/discord")]
|
|
public class DiscordController : Controller
|
|
{
|
|
private readonly AccessTokenCache _accessTokenCache;
|
|
private static HttpClient _httpClient;
|
|
private readonly DiscordInviteGenerator _inviteGenerator;
|
|
|
|
public DiscordController(
|
|
AccessTokenCache accessTokenCache,
|
|
DiscordInviteGenerator inviteGenerator,
|
|
HttpClient httpClient
|
|
)
|
|
{
|
|
_accessTokenCache = accessTokenCache;
|
|
_inviteGenerator = inviteGenerator;
|
|
_httpClient = httpClient;
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task<IActionResult> Index(string code = null)
|
|
{
|
|
Configuration config = new Configuration();
|
|
|
|
string redirectUri = $"{config.GetByKey<string>("Discord:BaseUri").GetValue()}/api/discord";
|
|
string clientId = config.GetByKey<string>("Discord:ClientId").GetValue();
|
|
string clientSecret = config.GetByKey<string>("Discord:ClientSecret").GetValue(readRestricted: true);
|
|
|
|
if (code == null)
|
|
return Redirect($"https://discord.com/api/oauth2/authorize?client_id={clientId}&redirect_uri={redirectUri}&response_type=code&scope=identify%20guilds");
|
|
|
|
Dictionary<string, string> values = new Dictionary<string, string>
|
|
{
|
|
{ "client_id", clientId },
|
|
{ "client_secret", clientSecret },
|
|
{ "grant_type", "authorization_code" },
|
|
{ "code", code },
|
|
{ "redirect_uri", redirectUri },
|
|
{ "scope", "identify guild" }
|
|
};
|
|
|
|
FormUrlEncodedContent content = new FormUrlEncodedContent(values);
|
|
HttpResponseMessage response = await _httpClient.PostAsync("https://discord.com/api/oauth2/token", content);
|
|
string responseString = await response.Content.ReadAsStringAsync();
|
|
DiscordOauthResponse responseObject = JsonConvert.DeserializeObject<DiscordOauthResponse>(responseString);
|
|
|
|
DiscordUserResponse userResponse = GetDiscordUser(responseObject.access_token);
|
|
if (_accessTokenCache.HasKey(responseObject.access_token))
|
|
_accessTokenCache.Remove(responseObject.access_token);
|
|
_accessTokenCache.Add(responseObject.access_token, userResponse.id, DateTime.Now.AddSeconds(responseObject.expires_in));
|
|
|
|
return LocalRedirect($"/#/?access_token={responseObject.access_token}");
|
|
}
|
|
|
|
[HttpGet("invite")]
|
|
public IActionResult Invite()
|
|
{
|
|
return Redirect(_inviteGenerator.Generate());
|
|
}
|
|
|
|
[HttpGet("user")]
|
|
public IActionResult GetUser()
|
|
{
|
|
if (!Request.Cookies.TryGetValue("access_token", out string accessToken))
|
|
accessToken = null;
|
|
|
|
DiscordUserResponse userResponse = GetDiscordUser(accessToken);
|
|
|
|
return Json(userResponse);
|
|
}
|
|
|
|
[HttpGet("guilds")]
|
|
public IActionResult GetGuilds()
|
|
{
|
|
if (!Request.Cookies.TryGetValue("access_token", out string accessToken))
|
|
accessToken = null;
|
|
|
|
HttpResponseMessage response;
|
|
using (HttpRequestMessage requestMessage =
|
|
new HttpRequestMessage(HttpMethod.Get, "https://discord.com/api/v7/users/@me/guilds"))
|
|
{
|
|
requestMessage.Headers.Authorization =
|
|
new AuthenticationHeaderValue("Bearer", accessToken);
|
|
response = _httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();
|
|
}
|
|
string responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
|
List<DiscordGuildResponse> userResponse = JsonConvert.DeserializeObject<List<DiscordGuildResponse>>(responseString);
|
|
|
|
List<ulong> presentGuilds = DiscordConnect._client.Guilds.Select(g => g.Id).ToList();
|
|
List<DiscordGuildResponseWithPresence> userResponseWithPresence =
|
|
userResponse
|
|
.Select(guild => guild.AddPresence(presentGuilds.Contains(Convert.ToUInt64(guild.id))))
|
|
.ToList();
|
|
|
|
return Json(userResponseWithPresence);
|
|
}
|
|
|
|
private static DiscordUserResponse GetDiscordUser(string accessToken)
|
|
{
|
|
HttpResponseMessage response;
|
|
using (HttpRequestMessage requestMessage =
|
|
new HttpRequestMessage(HttpMethod.Get, "https://discord.com/api/v7/users/@me"))
|
|
{
|
|
requestMessage.Headers.Authorization =
|
|
new AuthenticationHeaderValue("Bearer", accessToken);
|
|
response = _httpClient.SendAsync(requestMessage).GetAwaiter().GetResult();
|
|
}
|
|
|
|
string responseString = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
|
|
DiscordUserResponse userResponse = JsonConvert.DeserializeObject<DiscordUserResponse>(responseString);
|
|
return userResponse;
|
|
}
|
|
}
|
|
|
|
internal class DiscordOauthResponse
|
|
{
|
|
public string error { get; set; } = null;
|
|
public string error_description { get; set; } = null;
|
|
public string access_token { get; set; } = null;
|
|
public int expires_in { get; set; } = 0;
|
|
public string refresh_token { get; set; } = null;
|
|
public string scope { get; set; } = null;
|
|
public string token_type { get; set; } = null;
|
|
}
|
|
|
|
public class DiscordUserResponse
|
|
{
|
|
public string id { get; set; }
|
|
public string username { get; set; }
|
|
public string discriminator { get; set; }
|
|
public string avatar { get; set; } = null;
|
|
public bool bot { get; set; } = false;
|
|
public bool system { get; set; } = false;
|
|
public bool mfa_enabled { get; set; } = false;
|
|
public string locale { get; set; } = null;
|
|
public bool verified { get; set; } = false;
|
|
public string email { get; set; } = null;
|
|
public int flags { get; set; } = 0;
|
|
public int premium_type { get; set; } = 0;
|
|
public int public_flags { get; set; } = 0;
|
|
}
|
|
|
|
public class DiscordGuildResponse
|
|
{
|
|
public string id { get; set; }
|
|
public string name { get; set; }
|
|
public string icon { get; set; }
|
|
public bool owner { get; set; }
|
|
public int permissions { get; set; }
|
|
public int permissions_new { get; set; }
|
|
|
|
public DiscordGuildResponseWithPresence AddPresence(bool presence)
|
|
{
|
|
return new DiscordGuildResponseWithPresence
|
|
{
|
|
id = id,
|
|
name = name,
|
|
icon = icon,
|
|
owner = owner,
|
|
permissions = permissions,
|
|
permissions_new = permissions_new,
|
|
bot_present = presence
|
|
};
|
|
}
|
|
}
|
|
|
|
public class DiscordGuildResponseWithPresence : DiscordGuildResponse
|
|
{
|
|
public bool bot_present { get; set; }
|
|
}
|
|
}
|