This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
elliebot/src/EllieBot/Modules/Expressions/EllieExpressions.cs

445 lines
No EOL
14 KiB
C#

#nullable disable
using EllieBot.Db.Models;
namespace EllieBot.Modules.EllieExpressions;
[Name("Expressions")]
public partial class EllieExpressions : EllieModule<EllieExpressionsService>
{
public enum All
{
All
}
private readonly IBotCreds _creds;
private readonly IHttpClientFactory _clientFactory;
public EllieExpressions(IBotCreds creds, IHttpClientFactory clientFactory)
{
_creds = creds;
_clientFactory = clientFactory;
}
private bool AdminInGuildOrOwnerInDm()
=> (ctx.Guild is null && _creds.IsOwner(ctx.User))
|| (ctx.Guild is not null && ((IGuildUser)ctx.User).GuildPermissions.Administrator);
private async Task ExprAddInternalAsync(string key, string message)
{
if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key))
{
return;
}
var ex = await _service.AddAsync(ctx.Guild?.Id, key, message);
await Response()
.Embed(CreateEmbed()
.WithOkColor()
.WithTitle(GetText(strs.expr_new))
.WithDescription($"#{new kwum(ex.Id)}")
.AddField(GetText(strs.trigger), key)
.AddField(GetText(strs.response),
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
.SendAsync();
}
[Cmd]
[UserPerm(GuildPerm.Administrator)]
public async Task ExprToggleGlobal()
{
var result = await _service.ToggleGlobalExpressionsAsync(ctx.Guild.Id);
if (result)
await Response().Confirm(strs.expr_global_disabled).SendAsync();
else
await Response().Confirm(strs.expr_global_enabled).SendAsync();
}
[Cmd]
[UserPerm(GuildPerm.Administrator)]
public async Task ExprAddServer(string trigger, [Leftover] string response)
{
if (string.IsNullOrWhiteSpace(response) || string.IsNullOrWhiteSpace(trigger))
{
return;
}
await ExprAddInternalAsync(trigger, response);
}
[Cmd]
public async Task ExprAdd(string trigger, [Leftover] string response)
{
if (string.IsNullOrWhiteSpace(response) || string.IsNullOrWhiteSpace(trigger))
{
return;
}
if (!AdminInGuildOrOwnerInDm())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
await ExprAddInternalAsync(trigger, response);
}
[Cmd]
public async Task ExprEdit(kwum id, [Leftover] string message)
{
var channel = ctx.Channel as ITextChannel;
if (string.IsNullOrWhiteSpace(message) || id < 0)
{
return;
}
if (!IsValidExprEditor())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
var ex = await _service.EditAsync(ctx.Guild?.Id, id, message);
if (ex is not null)
{
await Response()
.Embed(CreateEmbed()
.WithOkColor()
.WithTitle(GetText(strs.expr_edited))
.WithDescription($"#{id}")
.AddField(GetText(strs.trigger), ex.Trigger)
.AddField(GetText(strs.response),
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
.SendAsync();
}
else
{
await Response().Error(strs.expr_no_found_id).SendAsync();
}
}
private bool IsValidExprEditor()
=> (ctx.Guild is not null && ((IGuildUser)ctx.User).GuildPermissions.Administrator)
|| (ctx.Guild is null && _creds.IsOwner(ctx.User));
[Cmd]
[Priority(1)]
public async Task ExprList(int page = 1)
{
if (--page < 0 || page > 999)
{
return;
}
var allExpressions = _service.GetExpressionsFor(ctx.Guild?.Id)
.OrderBy(x => x.Trigger)
.ToArray();
if (!allExpressions.Any())
{
await Response().Error(strs.expr_no_found).SendAsync();
return;
}
await Response()
.Paginated()
.Items(allExpressions)
.PageSize(20)
.CurrentPage(page)
.Page((exprs, _) =>
{
var desc = exprs
.Select(ex => $"{(ex.ContainsAnywhere ? "🗯" : "")}"
+ $"{(ex.DmResponse ? "" : "")}"
+ $"{(ex.AutoDeleteTrigger ? "" : "")}"
+ $"`{(kwum)ex.Id}` {ex.Trigger}"
+ (string.IsNullOrWhiteSpace(ex.Reactions)
? string.Empty
: " // " + string.Join(" ", ex.GetReactions())))
.Join('\n');
return CreateEmbed().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
})
.SendAsync();
}
[Cmd]
public async Task ExprShow(kwum id)
{
var found = _service.GetExpression(ctx.Guild?.Id, id);
if (found is null)
{
await Response().Error(strs.expr_no_found_id).SendAsync();
return;
}
var inter = CreateEditInteraction(id, found);
await Response()
.Interaction(IsValidExprEditor() ? inter : null)
.Embed(CreateEmbed()
.WithOkColor()
.WithDescription($"#{id}")
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
.AddField(GetText(strs.response),
found.Response.TrimTo(1000).Replace("](", "]\\(")))
.SendAsync();
}
private EllieInteractionBase CreateEditInteraction(kwum id, EllieExpression found)
{
var modal = new ModalBuilder()
.WithCustomId("expr:edit_modal")
.WithTitle($"Edit expression {id}")
.AddTextInput(new TextInputBuilder()
.WithLabel(GetText(strs.response))
.WithValue(found.Response)
.WithMinLength(1)
.WithCustomId("expr:edit_modal:response")
.WithStyle(TextInputStyle.Paragraph));
var inter = _inter.Create(ctx.User.Id,
new ButtonBuilder()
.WithEmote(Emoji.Parse("📝"))
.WithLabel("Edit")
.WithStyle(ButtonStyle.Primary)
.WithCustomId("test"),
modal,
async (sm) =>
{
var msg = sm.Data.Components.FirstOrDefault()?.Value;
await ExprEdit(id, msg);
}
);
return inter;
}
public async Task ExprDeleteInternalAsync(kwum id)
{
var ex = await _service.DeleteAsync(ctx.Guild?.Id, id);
if (ex is not null)
{
await Response()
.Embed(CreateEmbed()
.WithOkColor()
.WithTitle(GetText(strs.expr_deleted))
.WithDescription($"#{id}")
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)))
.SendAsync();
}
else
{
await Response().Error(strs.expr_no_found_id).SendAsync();
}
}
[Cmd]
[UserPerm(GuildPerm.Administrator)]
[RequireContext(ContextType.Guild)]
public async Task ExprDeleteServer(kwum id)
=> await ExprDeleteInternalAsync(id);
[Cmd]
public async Task ExprDelete(kwum id)
{
if (!AdminInGuildOrOwnerInDm())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
await ExprDeleteInternalAsync(id);
}
[Cmd]
public async Task ExprReact(kwum id, params string[] emojiStrs)
{
if (!AdminInGuildOrOwnerInDm())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
var ex = _service.GetExpression(ctx.Guild?.Id, id);
if (ex is null)
{
await Response().Error(strs.expr_no_found_id).SendAsync();
return;
}
if (emojiStrs.Length == 0)
{
await _service.ResetExprReactions(ctx.Guild?.Id, id);
await Response().Confirm(strs.expr_reset(Format.Bold(id.ToString()))).SendAsync();
return;
}
var succ = new List<string>();
foreach (var emojiStr in emojiStrs)
{
var emote = emojiStr.ToIEmote();
// i should try adding these emojis right away to the message, to make sure the bot can react with these emojis. If it fails, skip that emoji
try
{
await ctx.Message.AddReactionAsync(emote);
await Task.Delay(100);
succ.Add(emojiStr);
if (succ.Count >= 3)
{
break;
}
}
catch { }
}
if (succ.Count == 0)
{
await Response().Error(strs.invalid_emojis).SendAsync();
return;
}
await _service.SetExprReactions(ctx.Guild?.Id, id, succ);
await Response()
.Confirm(strs.expr_set(Format.Bold(id.ToString()),
succ.Select(static x => x.ToString()).Join(", ")))
.SendAsync();
}
[Cmd]
public Task ExprCa(kwum id)
=> InternalExprEdit(id, ExprField.ContainsAnywhere);
[Cmd]
public Task ExprDm(kwum id)
=> InternalExprEdit(id, ExprField.DmResponse);
[Cmd]
public Task ExprAd(kwum id)
=> InternalExprEdit(id, ExprField.AutoDelete);
[Cmd]
public Task ExprAt(kwum id)
=> InternalExprEdit(id, ExprField.AllowTarget);
[Cmd]
[OwnerOnly]
public async Task ExprsReload()
{
await _service.TriggerReloadExpressions();
await ctx.OkAsync();
}
private async Task InternalExprEdit(kwum id, ExprField option)
{
if (!AdminInGuildOrOwnerInDm())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
var (success, newVal) = await _service.ToggleExprOptionAsync(ctx.Guild?.Id, id, option);
if (!success)
{
await Response().Error(strs.expr_no_found_id).SendAsync();
return;
}
if (newVal)
{
await Response()
.Confirm(strs.option_enabled(Format.Code(option.ToString()),
Format.Code(id.ToString())))
.SendAsync();
}
else
{
await Response()
.Confirm(strs.option_disabled(Format.Code(option.ToString()),
Format.Code(id.ToString())))
.SendAsync();
}
}
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
public async Task ExprClear()
{
if (await PromptUserConfirmAsync(CreateEmbed()
.WithTitle("Expression clear")
.WithDescription("This will delete all expressions on this server.")))
{
var count = _service.DeleteAllExpressions(ctx.Guild.Id);
await Response().Confirm(strs.exprs_cleared(count)).SendAsync();
}
}
[Cmd]
public async Task ExprsExport()
{
if (!AdminInGuildOrOwnerInDm())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
_ = ctx.Channel.TriggerTypingAsync();
var serialized = _service.ExportExpressions(ctx.Guild?.Id);
await using var stream = await serialized.ToStream();
await ctx.User.SendFileAsync(stream, $"exprs-export_{DateTime.UtcNow:yyyy-MM-dd-HH-mm-ss}_{(ctx.Guild?.Id.ToString() ?? "global")}.yml");
}
[Cmd]
[Ratelimit(300)]
public async Task ExprsImport([Leftover] string input = null)
{
if (!AdminInGuildOrOwnerInDm())
{
await Response().Error(strs.expr_insuff_perms).SendAsync();
return;
}
input = input?.Trim();
_ = ctx.Channel.TriggerTypingAsync();
if (input is null)
{
var attachment = ctx.Message.Attachments.FirstOrDefault();
if (attachment is null)
{
await Response().Error(strs.expr_import_no_input).SendAsync();
return;
}
using var client = _clientFactory.CreateClient();
input = await client.GetStringAsync(attachment.Url);
if (string.IsNullOrWhiteSpace(input))
{
await Response().Error(strs.expr_import_no_input).SendAsync();
return;
}
}
var succ = await _service.ImportExpressionsAsync(ctx.Guild?.Id, input);
if (!succ)
{
await Response().Error(strs.expr_import_invalid_data).SendAsync();
return;
}
await ctx.OkAsync();
}
}