PluralKit/PluralKit.Bot/Commands/Autoproxy.cs

132 lines
6.5 KiB
C#
Raw Normal View History

2020-04-24 19:50:28 +00:00
using System;
2020-01-23 20:20:22 +00:00
using System.Threading.Tasks;
using Dapper;
2020-04-24 19:50:28 +00:00
using DSharpPlus.Entities;
2020-01-23 20:20:22 +00:00
using PluralKit.Core;
2020-01-23 20:20:22 +00:00
namespace PluralKit.Bot
2020-01-23 20:20:22 +00:00
{
2020-02-01 12:03:02 +00:00
public class Autoproxy
2020-01-23 20:20:22 +00:00
{
private readonly Database _db;
2020-01-23 20:20:22 +00:00
public Autoproxy(Database db)
2020-01-23 20:20:22 +00:00
{
_db = db;
2020-01-23 20:20:22 +00:00
}
2020-02-01 12:03:02 +00:00
public async Task AutoproxyRoot(Context ctx)
2020-01-23 20:20:22 +00:00
{
ctx.CheckSystem().CheckGuildContext();
if (ctx.Match("off", "stop", "cancel", "no"))
await AutoproxyOff(ctx);
else if (ctx.Match("latch", "last", "proxy", "stick", "sticky"))
await AutoproxyLatch(ctx);
else if (ctx.Match("front", "fronter", "switch"))
await AutoproxyFront(ctx);
else if (ctx.Match("member"))
throw new PKSyntaxError("Member-mode autoproxy must target a specific member. Use the `pk;autoproxy <member>` command, where `member` is the name or ID of a member in your system.");
else if (await ctx.MatchMember() is PKMember member)
await AutoproxyMember(ctx, member);
else if (!ctx.HasNext())
await ctx.Reply(embed: await CreateAutoproxyStatusEmbed(ctx));
else
throw new PKSyntaxError($"Invalid autoproxy mode `{ctx.PopArgument().EscapeMarkdown()}`.");
}
private async Task AutoproxyOff(Context ctx)
{
if (ctx.MessageContext.AutoproxyMode == AutoproxyMode.Off)
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Note} Autoproxy is already off in this server.");
else
{
await UpdateAutoproxy(ctx, AutoproxyMode.Off, null);
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Success} Autoproxy turned off in this server.");
}
}
private async Task AutoproxyLatch(Context ctx)
{
if (ctx.MessageContext.AutoproxyMode == AutoproxyMode.Latch)
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Note} Autoproxy is already set to latch mode in this server. If you want to disable autoproxying, use `pk;autoproxy off`.");
else
{
await UpdateAutoproxy(ctx, AutoproxyMode.Latch, null);
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Success} Autoproxy set to latch mode in this server. Messages will now be autoproxied using the *last-proxied member* in this server.");
}
}
private async Task AutoproxyFront(Context ctx)
{
if (ctx.MessageContext.AutoproxyMode == AutoproxyMode.Front)
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Note} Autoproxy is already set to front mode in this server. If you want to disable autoproxying, use `pk;autoproxy off`.");
else
{
await UpdateAutoproxy(ctx, AutoproxyMode.Front, null);
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Success} Autoproxy set to front mode in this server. Messages will now be autoproxied using the *current first fronter*, if any.");
}
}
private async Task AutoproxyMember(Context ctx, PKMember member)
{
ctx.CheckOwnMember(member);
await UpdateAutoproxy(ctx, AutoproxyMode.Member, member.Id);
2020-01-23 20:20:22 +00:00
await ctx.Reply($"{Emojis.Success} Autoproxy set to **{member.Name}** in this server.");
}
2020-04-24 19:50:28 +00:00
private async Task<DiscordEmbed> CreateAutoproxyStatusEmbed(Context ctx)
2020-01-23 20:20:22 +00:00
{
var commandList = "**pk;autoproxy latch** - Autoproxies as last-proxied member\n**pk;autoproxy front** - Autoproxies as current (first) fronter\n**pk;autoproxy <member>** - Autoproxies as a specific member";
2020-04-24 19:50:28 +00:00
var eb = new DiscordEmbedBuilder().WithTitle($"Current autoproxy status (for {ctx.Guild.Name.EscapeMarkdown()})");
var fronters = ctx.MessageContext.LastSwitchMembers;
var relevantMember = ctx.MessageContext.AutoproxyMode switch
{
AutoproxyMode.Front => fronters.Count > 0 ? await _db.Execute(c => c.QueryMember(fronters[0])) : null,
AutoproxyMode.Member => await _db.Execute(c => c.QueryMember(ctx.MessageContext.AutoproxyMember.Value)),
_ => null
};
2020-01-23 20:20:22 +00:00
switch (ctx.MessageContext.AutoproxyMode) {
2020-01-23 20:20:22 +00:00
case AutoproxyMode.Off: eb.WithDescription($"Autoproxy is currently **off** in this server. To enable it, use one of the following commands:\n{commandList}");
break;
case AutoproxyMode.Front:
{
if (fronters.Count == 0)
eb.WithDescription("Autoproxy is currently set to **front mode** in this server, but there are currently no fronters registered. Use the `pk;switch` command to log a switch.");
2020-01-23 20:20:22 +00:00
else
{
if (relevantMember == null)
throw new ArgumentException("Attempted to print member autoproxy status, but the linked member ID wasn't found in the database. Should be handled appropriately.");
eb.WithDescription($"Autoproxy is currently set to **front mode** in this server. The current (first) fronter is **{relevantMember.Name.EscapeMarkdown()}** (`{relevantMember.Hid}`). To disable, type `pk;autoproxy off`.");
2020-01-23 20:20:22 +00:00
}
break;
}
// AutoproxyMember is never null if Mode is Member, this is just to make the compiler shut up
case AutoproxyMode.Member when relevantMember != null: {
eb.WithDescription($"Autoproxy is active for member **{relevantMember.Name}** (`{relevantMember.Hid}`) in this server. To disable, type `pk;autoproxy off`.");
2020-01-23 20:20:22 +00:00
break;
}
case AutoproxyMode.Latch:
eb.WithDescription("Autoproxy is currently set to **latch mode**, meaning the *last-proxied member* will be autoproxied. To disable, type `pk;autoproxy off`.");
2020-01-23 20:20:22 +00:00
break;
2020-01-23 20:20:22 +00:00
default: throw new ArgumentOutOfRangeException();
}
return eb.Build();
}
private Task UpdateAutoproxy(Context ctx, AutoproxyMode autoproxyMode, int? autoproxyMember) =>
_db.Execute(c =>
c.ExecuteAsync(
"update system_guild set autoproxy_mode = @autoproxyMode, autoproxy_member = @autoproxyMember where guild = @guild and system = @system",
new {autoproxyMode, autoproxyMember, guild = ctx.Guild.Id, system = ctx.System.Id}));
2020-01-23 20:20:22 +00:00
}
}