Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: check delete days parameter before executing a ban #51

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
57 changes: 50 additions & 7 deletions Zhongli.Bot/Modules/Moderation/ModerationModule.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.Addons.Interactive;
using Discord.Addons.Interactive.Paginator;
using Discord.Commands;
using Humanizer;
using Zhongli.Data;
Expand All @@ -18,7 +21,7 @@ namespace Zhongli.Bot.Modules.Moderation
{
[Name("Moderation")]
[Summary("Guild moderation commands.")]
public class ModerationModule : ModuleBase<SocketCommandContext>
public class ModerationModule : InteractiveBase
{
private readonly CommandErrorHandler _error;
private readonly ModerationLoggingService _logging;
Expand All @@ -44,13 +47,20 @@ public ModerationModule(
public async Task BanAsync(IUser user, uint deleteDays = 0, TimeSpan? length = null,
[Remainder] string? reason = null)
{
var details = await GetDetailsAsync(user, reason);
var result = await _moderation.TryBanAsync(deleteDays, length, details);

if (result is null)
await _error.AssociateError(Context.Message, "Failed to ban user.");
if (deleteDays < 0 || deleteDays > 7)
{
await ReplyAsync($"Error: Parameter deleteDays cannot be higher than 7, {deleteDays} given.");
}
else
await ReplyReprimandAsync(result, details);
{
var details = await GetDetailsAsync(user, reason);
var result = await _moderation.TryBanAsync(deleteDays, length, details);

if (result is null)
await _error.AssociateError(Context.Message, "Failed to ban user.");
else
await ReplyReprimandAsync(result, details);
}
}

[Command("ban")]
Expand Down Expand Up @@ -234,6 +244,35 @@ public async Task WarnAsync(IGuildUser user, uint amount = 1, [Remainder] string
public Task WarnAsync(IGuildUser user, [Remainder] string? reason = null)
=> WarnAsync(user, 1, reason);

[Command("mute list")]
[Summary("View active mutes on the current guild.")]
[RequireAuthorization(AuthorizationScope.Moderator)]
public async Task MuteListAsync()
{
var guild = await _db.Guilds.TrackGuildAsync(Context.Guild);
var history = guild.ReprimandHistory
.Where(r => r.Status is not ReprimandStatus.Deleted && r.Status is not ReprimandStatus.Expired)
.OfType(InfractionType.Mute);

var reprimands = new EmbedBuilder().Fields;

var pages = history
.OrderByDescending(r => r.Action?.Date)
.Select(r => CreateEmbed(r));

var message = new PaginatedMessage
{
Title = "Currently Active Mutes",
Pages = reprimands.Concat(pages),
Options = new PaginatedAppearanceOptions
{
FieldsPerPage = 10
}
};

await PagedReplyAsync(message);
}

private async Task ReplyReprimandAsync(ReprimandResult result, ReprimandDetails details)
{
var guild = await result.Primary.GetGuildAsync(_db);
Expand Down Expand Up @@ -267,5 +306,9 @@ private async Task<ReprimandDetails> GetDetailsAsync(IUser user, string? reason)

return details;
}

private static EmbedFieldBuilder CreateEmbed(Reprimand r) => new EmbedFieldBuilder()
.WithName(r.GetTitle())
.WithValue(r.GetReprimandExpiration());
}
}
2 changes: 1 addition & 1 deletion Zhongli.Services/Moderation/ModerationLoggingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task<EmbedBuilder> UpdatedEmbedAsync(Reprimand reprimand, Reprimand
.WithTitle($"{reprimand.Status.Humanize()} {reprimand.GetTitle()}")
.WithColor(Color.Purple);

AddReason(embed, reprimand.ModifiedAction);
AddReason(embed, reprimand.Action);
await AddReprimandDetailsAsync(embed, reprimand, cancellationToken);

return embed;
Expand Down
4 changes: 2 additions & 2 deletions Zhongli.Services/Moderation/ModerationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,8 @@ private async Task ExpireReprimandAsync(ExpirableReprimand reprimand, Cancellati
private async Task UpdateReprimandAsync(Reprimand reprimand, ReprimandDetails details,
ReprimandStatus status, CancellationToken cancellationToken)
{
reprimand.Status = status;
reprimand.ModifiedAction = details;
reprimand.Status = status;
reprimand.Action = details;

await _db.SaveChangesAsync(cancellationToken);
await _logging.PublishReprimandAsync(reprimand, details, cancellationToken);
Expand Down
36 changes: 36 additions & 0 deletions Zhongli.Services/Moderation/ReprimandExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,42 @@ public static bool IsIncluded(this Reprimand reprimand, ReprimandNoticeType type
};
}

public static string GetExpirationTime(this IExpirable expirable)
{
if (expirable.ExpireAt is not null && expirable.Length is not null)
{
if (expirable.ExpireAt > DateTimeOffset.Now)
{
TimeSpan? dif = expirable.ExpireAt - DateTimeOffset.Now;
return $"{(int)dif.Value.TotalDays} days {dif.Value.Hours} hours {dif.Value.Minutes} minutes {dif.Value.Seconds} seconds";

}
else
{
return "Now";
}
}
else
{
return "Indefinitely";
}
}

public static string GetReprimandExpiration(this Reprimand reprimand)
{
var mention = $"<@{reprimand.UserId}>";
var line = reprimand switch
{
Ban b => $"Expired in: {b.GetExpirationTime()}.",
Mute m => $"Expired in: {m.GetExpirationTime()}.",
_ => throw new ArgumentOutOfRangeException(
nameof(reprimand), reprimand, "This reprimand is not expirable.")
};
return new StringBuilder()
.AppendLine($"User: {mention}")
.AppendLine(line).ToString();
}

public static Color GetColor(this Reprimand reprimand)
{
return reprimand switch
Expand Down