chaosbot/ChaosBot/WebServer/App/DiscordController.cs

186 lines
7.4 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.Discord;
using ChaosBot.Repositories;
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 static readonly AccessTokenCache Cache = WebServer.Cache;
private static readonly HttpClient client = new HttpClient();
[HttpGet]
public async Task<IActionResult> Index(string code = null)
{
string redirectUri = $"{Program.AppSettingsHandler.GetValue<string>("Discord:BaseUri")}/api/discord";
string clientId = Program.AppSettingsHandler.GetValue<string>("Discord:ClientId");
string clientSecret = Program.AppSettingsHandler.GetValue<string>("Discord:ClientSecret");
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 client.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 (Cache.HasKey(responseObject.access_token))
Cache.Remove(responseObject.access_token);
Cache.Add(responseObject.access_token, userResponse.id, DateTime.Now.AddSeconds(responseObject.expires_in));
return LocalRedirect($"/#/?access_token={responseObject.access_token}");
}
[HttpGet("invite")]
public IActionResult Invite()
{
string clientId = Program.AppSettingsHandler.GetValue<string>("Discord:ClientId");
const ulong permissions =
0x00000020 + // MANAGE_CHANNELS
0x04000000 + // CHANGE_NICKNAME
0x00010000 + // READ_MESSAGE_HISTORY
0x00000800 + // SEND_MESSAGES
0x00002000 + // MANAGE_MESSAGES
0x00008000 + // ATTACH_FILES
0x00040000 + // USE_EXTERNAL_EMOJIS
0x00000040 + // ADD_REACTIONS
0x00000400 // VIEW_CHANNEL
;
return Redirect($"https://discord.com/oauth2/authorize?client_id={clientId}&scope=bot&permissions={permissions}");
}
[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 = client.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(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 = client.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 ulong 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; }
}
}