Port more things!

This commit is contained in:
Ske
2020-12-24 14:52:44 +01:00
parent f6fb8204bb
commit 47b16dc51b
26 changed files with 332 additions and 186 deletions

View File

@@ -13,7 +13,16 @@ using Humanizer;
using NodaTime;
using PluralKit.Core;
using DSharpPlus.Entities;
using Myriad.Builders;
using Myriad.Cache;
using Myriad.Extensions;
using Myriad.Gateway;
using Myriad.Rest;
using Myriad.Rest.Types.Requests;
using Myriad.Types;
using Permissions = DSharpPlus.Permissions;
namespace PluralKit.Bot {
public class Misc
@@ -25,8 +34,12 @@ namespace PluralKit.Bot {
private readonly EmbedService _embeds;
private readonly IDatabase _db;
private readonly ModelRepository _repo;
private readonly IDiscordCache _cache;
private readonly DiscordApiClient _rest;
private readonly Cluster _cluster;
private readonly Bot _bot;
public Misc(BotConfig botConfig, IMetrics metrics, CpuStatService cpu, ShardInfoService shards, EmbedService embeds, ModelRepository repo, IDatabase db)
public Misc(BotConfig botConfig, IMetrics metrics, CpuStatService cpu, ShardInfoService shards, EmbedService embeds, ModelRepository repo, IDatabase db, IDiscordCache cache, DiscordApiClient rest, Bot bot, Cluster cluster)
{
_botConfig = botConfig;
_metrics = metrics;
@@ -35,20 +48,26 @@ namespace PluralKit.Bot {
_embeds = embeds;
_repo = repo;
_db = db;
_cache = cache;
_rest = rest;
_bot = bot;
_cluster = cluster;
}
public async Task Invite(Context ctx)
{
var clientId = _botConfig.ClientId ?? ctx.Client.CurrentApplication.Id;
var permissions = new Permissions()
.Grant(Permissions.AddReactions)
.Grant(Permissions.AttachFiles)
.Grant(Permissions.EmbedLinks)
.Grant(Permissions.ManageMessages)
.Grant(Permissions.ManageWebhooks)
.Grant(Permissions.ReadMessageHistory)
.Grant(Permissions.SendMessages);
var invite = $"https://discord.com/oauth2/authorize?client_id={clientId}&scope=bot%20applications.commands&permissions={(long)permissions}";
var clientId = _botConfig.ClientId ?? _cluster.Application?.Id;
var permissions =
PermissionSet.AddReactions |
PermissionSet.AttachFiles |
PermissionSet.EmbedLinks |
PermissionSet.ManageMessages |
PermissionSet.ManageWebhooks |
PermissionSet.ReadMessageHistory |
PermissionSet.SendMessages;
var invite = $"https://discord.com/oauth2/authorize?client_id={clientId}&scope=bot%20applications.commands&permissions={(ulong)permissions}";
await ctx.Reply($"{Emojis.Success} Use this link to add PluralKit to your server:\n<{invite}>");
}
@@ -69,6 +88,7 @@ namespace PluralKit.Bot {
var totalSwitches = _metrics.Snapshot.GetForContext("Application").Gauges.FirstOrDefault(m => m.MultidimensionalName == CoreMetrics.SwitchCount.Name)?.Value ?? 0;
var totalMessages = _metrics.Snapshot.GetForContext("Application").Gauges.FirstOrDefault(m => m.MultidimensionalName == CoreMetrics.MessageCount.Name)?.Value ?? 0;
// TODO: shard stuff
var shardId = ctx.Shard.ShardId;
var shardTotal = ctx.Client.ShardClients.Count;
var shardUpTotal = _shards.Shards.Where(x => x.Connected).Count();
@@ -79,30 +99,31 @@ namespace PluralKit.Bot {
var shardUptime = SystemClock.Instance.GetCurrentInstant() - shardInfo.LastConnectionTime;
var embed = new DiscordEmbedBuilder();
if (messagesReceived != null) embed.AddField("Messages processed",$"{messagesReceived.OneMinuteRate * 60:F1}/m ({messagesReceived.FifteenMinuteRate * 60:F1}/m over 15m)", true);
if (messagesProxied != null) embed.AddField("Messages proxied", $"{messagesProxied.OneMinuteRate * 60:F1}/m ({messagesProxied.FifteenMinuteRate * 60:F1}/m over 15m)", true);
if (commandsRun != null) embed.AddField("Commands executed", $"{commandsRun.OneMinuteRate * 60:F1}/m ({commandsRun.FifteenMinuteRate * 60:F1}/m over 15m)", true);
var embed = new EmbedBuilder();
if (messagesReceived != null) embed.Field(new("Messages processed",$"{messagesReceived.OneMinuteRate * 60:F1}/m ({messagesReceived.FifteenMinuteRate * 60:F1}/m over 15m)", true));
if (messagesProxied != null) embed.Field(new("Messages proxied", $"{messagesProxied.OneMinuteRate * 60:F1}/m ({messagesProxied.FifteenMinuteRate * 60:F1}/m over 15m)", true));
if (commandsRun != null) embed.Field(new("Commands executed", $"{commandsRun.OneMinuteRate * 60:F1}/m ({commandsRun.FifteenMinuteRate * 60:F1}/m over 15m)", true));
embed
.AddField("Current shard", $"Shard #{shardId} (of {shardTotal} total, {shardUpTotal} are up)", true)
.AddField("Shard uptime", $"{shardUptime.FormatDuration()} ({shardInfo.DisconnectionCount} disconnections)", true)
.AddField("CPU usage", $"{_cpu.LastCpuMeasure:P1}", true)
.AddField("Memory usage", $"{memoryUsage / 1024 / 1024} MiB", true)
.AddField("Latency", $"API: {apiLatency.TotalMilliseconds:F0} ms, shard: {shardInfo.ShardLatency.Milliseconds} ms", true)
.AddField("Total numbers", $"{totalSystems:N0} systems, {totalMembers:N0} members, {totalGroups:N0} groups, {totalSwitches:N0} switches, {totalMessages:N0} messages");
await msg.ModifyAsync("", embed.Build());
.Field(new("Current shard", $"Shard #{shardId} (of {shardTotal} total, {shardUpTotal} are up)", true))
.Field(new("Shard uptime", $"{shardUptime.FormatDuration()} ({shardInfo.DisconnectionCount} disconnections)", true))
.Field(new("CPU usage", $"{_cpu.LastCpuMeasure:P1}", true))
.Field(new("Memory usage", $"{memoryUsage / 1024 / 1024} MiB", true))
.Field(new("Latency", $"API: {apiLatency.TotalMilliseconds:F0} ms, shard: {shardInfo.ShardLatency.Milliseconds} ms", true))
.Field(new("Total numbers", $"{totalSystems:N0} systems, {totalMembers:N0} members, {totalGroups:N0} groups, {totalSwitches:N0} switches, {totalMessages:N0} messages"));
await ctx.RestNew.EditMessage(msg.ChannelId, msg.Id,
new MessageEditRequest {Content = "", Embed = embed.Build()});
}
public async Task PermCheckGuild(Context ctx)
{
DiscordGuild guild;
DiscordMember senderGuildUser = null;
Guild guild;
GuildMemberPartial senderGuildUser = null;
if (ctx.Guild != null && !ctx.HasNext())
if (ctx.GuildNew != null && !ctx.HasNext())
{
guild = ctx.Guild;
senderGuildUser = (DiscordMember)ctx.Author;
guild = ctx.GuildNew;
senderGuildUser = ctx.MemberNew;
}
else
{
@@ -110,31 +131,33 @@ namespace PluralKit.Bot {
if (!ulong.TryParse(guildIdStr, out var guildId))
throw new PKSyntaxError($"Could not parse {guildIdStr.AsCode()} as an ID.");
guild = ctx.Client.GetGuild(guildId);
if (guild != null) senderGuildUser = await guild.GetMember(ctx.Author.Id);
if (guild == null || senderGuildUser == null) throw Errors.GuildNotFound(guildId);
guild = await _rest.GetGuild(guildId);
if (guild != null)
senderGuildUser = await _rest.GetGuildMember(guildId, ctx.AuthorNew.Id);
if (guild == null || senderGuildUser == null)
throw Errors.GuildNotFound(guildId);
}
var requiredPermissions = new []
{
Permissions.AccessChannels,
Permissions.SendMessages,
Permissions.AddReactions,
Permissions.AttachFiles,
Permissions.EmbedLinks,
Permissions.ManageMessages,
Permissions.ManageWebhooks
PermissionSet.ViewChannel,
PermissionSet.SendMessages,
PermissionSet.AddReactions,
PermissionSet.AttachFiles,
PermissionSet.EmbedLinks,
PermissionSet.ManageMessages,
PermissionSet.ManageWebhooks
};
// Loop through every channel and group them by sets of permissions missing
var permissionsMissing = new Dictionary<ulong, List<DiscordChannel>>();
var permissionsMissing = new Dictionary<ulong, List<Channel>>();
var hiddenChannels = 0;
foreach (var channel in await guild.GetChannelsAsync())
foreach (var channel in await _rest.GetGuildChannels(guild.Id))
{
var botPermissions = channel.BotPermissions();
var botPermissions = _bot.PermissionsIn(channel.Id);
var userPermissions = PermissionExtensions.PermissionsFor(guild, channel, ctx.AuthorNew.Id, senderGuildUser.Roles);
var userPermissions = senderGuildUser.PermissionsIn(channel);
if ((userPermissions & Permissions.AccessChannels) == 0)
if ((userPermissions & PermissionSet.ViewChannel) == 0)
{
// If the user can't see this channel, don't calculate permissions for it
// (to prevent info-leaking, mostly)
@@ -154,18 +177,18 @@ namespace PluralKit.Bot {
// This means we can check if the dict is empty to see if all channels are proxyable
if (missingPermissionField != 0)
{
permissionsMissing.TryAdd(missingPermissionField, new List<DiscordChannel>());
permissionsMissing.TryAdd(missingPermissionField, new List<Channel>());
permissionsMissing[missingPermissionField].Add(channel);
}
}
// Generate the output embed
var eb = new DiscordEmbedBuilder()
.WithTitle($"Permission check for **{guild.Name}**");
var eb = new EmbedBuilder()
.Title($"Permission check for **{guild.Name}**");
if (permissionsMissing.Count == 0)
{
eb.WithDescription($"No errors found, all channels proxyable :)").WithColor(DiscordUtils.Green);
eb.Description($"No errors found, all channels proxyable :)").Color((uint?) DiscordUtils.Green.Value);
}
else
{
@@ -173,18 +196,19 @@ namespace PluralKit.Bot {
{
// Each missing permission field can have multiple missing channels
// so we extract them all and generate a comma-separated list
// TODO: port ToPermissionString?
var missingPermissionNames = ((Permissions)missingPermissionField).ToPermissionString();
var channelsList = string.Join("\n", channels
.OrderBy(c => c.Position)
.Select(c => $"#{c.Name}"));
eb.AddField($"Missing *{missingPermissionNames}*", channelsList.Truncate(1000));
eb.WithColor(DiscordUtils.Red);
eb.Field(new($"Missing *{missingPermissionNames}*", channelsList.Truncate(1000)));
eb.Color((uint?) DiscordUtils.Red.Value);
}
}
if (hiddenChannels > 0)
eb.WithFooter($"{"channel".ToQuantity(hiddenChannels)} were ignored as you do not have view access to them.");
eb.Footer(new($"{"channel".ToQuantity(hiddenChannels)} were ignored as you do not have view access to them."));
// Send! :)
await ctx.Reply(embed: eb.Build());