1
0
Fork 1
mirror of https://github.com/TeamOctolings/Octobot.git synced 2025-01-31 09:09:00 +03:00

(Almost) Final implementation of /warn

Signed-off-by: mctaylors <cantsendmails@mctaylors.ru>
This commit is contained in:
Macintxsh 2024-03-26 20:59:56 +03:00
parent 2564277070
commit 152682e456
Signed by: mctaylors
GPG key ID: 7181BEBE676903C1
6 changed files with 253 additions and 102 deletions

View file

@ -693,7 +693,7 @@
<data name="YourWarningsHaveBeenRevoked" xml:space="preserve">
<value>Your warnings have been revoked</value>
</data>
<data name="DescriptionActionWarns" xml:space="preserve">
<data name="DescriptionWarns" xml:space="preserve">
<value>Warns: {0}</value>
</data>
<data name="UserHasNoWarnings" xml:space="preserve">
@ -711,7 +711,7 @@
<data name="SettingsWarnPunishmentDuration" xml:space="preserve">
<value>Punishment duration for warnings</value>
</data>
<data name="ListWarnTitle" xml:space="preserve">
<data name="ListExecutorWarnsTitle" xml:space="preserve">
<value>Here's your warnings, {0}:</value>
</data>
<data name="YouHaveNoWarnings" xml:space="preserve">
@ -762,4 +762,37 @@
<data name="BotCannotUnwarnTarget" xml:space="preserve">
<value>I cannot unwarn this member!</value>
</data>
<data name="UserCannotGetWarnsBot" xml:space="preserve">
<value>You cannot get my warns!</value>
</data>
<data name="UserCannotGetWarnsOwner" xml:space="preserve">
<value>You cannot get owner's warns!</value>
</data>
<data name="UserCannotGetWarnsTarget" xml:space="preserve">
<value>You cannot get warns of this member!</value>
</data>
<data name="UserCannotGetWarnsThemselves" xml:space="preserve">
<value>Use this command without options instead.</value>
</data>
<data name="UserCannotWarnMembers" xml:space="preserve">
<value>You cannot warn members in this guild!</value>
</data>
<data name="UserCannotUnwarnMembers" xml:space="preserve">
<value>You cannot unwarn members in this guild!</value>
</data>
<data name="UserCannotGetWarnsMembers" xml:space="preserve">
<value>You cannot get warns of other members in this guild!</value>
</data>
<data name="ListTargetWarnsTitle" xml:space="preserve">
<value>Warnings given to {0}:</value>
</data>
<data name="DescriptionPunishmentType" xml:space="preserve">
<value>Punishment type: {0}</value>
</data>
<data name="WarnThresholdExceeded" xml:space="preserve">
<value>Warn threshold has been exceeded. ({0})</value>
</data>
<data name="WarnPunishmentDurationNotSet" xml:space="preserve">
<value>The WarnPunishmentDuration setting is not set for the current punishment type.</value>
</data>
</root>

View file

@ -693,7 +693,7 @@
<data name="YourWarningsHaveBeenRevoked" xml:space="preserve">
<value>Ваши предупреждения были отозваны</value>
</data>
<data name="DescriptionActionWarns" xml:space="preserve">
<data name="DescriptionWarns" xml:space="preserve">
<value>Предупреждений: {0}</value>
</data>
<data name="UserHasNoWarnings" xml:space="preserve">
@ -711,7 +711,7 @@
<data name="SettingsWarnPunishmentDuration" xml:space="preserve">
<value>Длительность наказания для предупреждений</value>
</data>
<data name="ListWarnTitle" xml:space="preserve">
<data name="ListExecutorWarnsTitle" xml:space="preserve">
<value>Вот ваши предупреждения, {0}:</value>
</data>
<data name="YouHaveNoWarnings" xml:space="preserve">
@ -762,4 +762,37 @@
<data name="BotCannotWarnMembers" xml:space="preserve">
<value>Я не могу предупреждать участников этого сервера!</value>
</data>
<data name="UserCannotGetWarnsBot" xml:space="preserve">
<value>Ты не можешь просмотреть мои предупреждения!</value>
</data>
<data name="UserCannotGetWarnsOwner" xml:space="preserve">
<value>Ты не можешь просмотреть предупреждения владельца этого сервера!</value>
</data>
<data name="UserCannotGetWarnsTarget" xml:space="preserve">
<value>Ты не можешь просмотреть предупреждения этого участника!</value>
</data>
<data name="UserCannotGetWarnsThemselves" xml:space="preserve">
<value>Вместо этого, используйте эту команду без параметров.</value>
</data>
<data name="UserCannotUnwarnMembers" xml:space="preserve">
<value>Ты не можешь снимать предупреждения с участников этого сервера!</value>
</data>
<data name="UserCannotWarnMembers" xml:space="preserve">
<value>Ты не можешь предупреждать участников этого сервера!</value>
</data>
<data name="UserCannotGetWarnsMembers" xml:space="preserve">
<value>Ты не можешь просматривать предупреждения участников этого сервера!</value>
</data>
<data name="ListTargetWarnsTitle" xml:space="preserve">
<value>Предупреждения пользователя {0}:</value>
</data>
<data name="DescriptionPunishmentType" xml:space="preserve">
<value>Тип наказания: {0}</value>
</data>
<data name="WarnThresholdExceeded" xml:space="preserve">
<value>Превышен порог предупреждений. ({0})</value>
</data>
<data name="WarnPunishmentDurationNotSet" xml:space="preserve">
<value>Настройка WarnPunishmentDuration не установлена для текущего типа наказания.</value>
</data>
</root>

View file

@ -693,7 +693,7 @@
<data name="YourWarningsHaveBeenRevoked" xml:space="preserve">
<value>вы получили карт-бланш</value>
</data>
<data name="DescriptionActionWarns" xml:space="preserve">
<data name="DescriptionWarns" xml:space="preserve">
<value>варнов: {0}</value>
</data>
<data name="UserHasNoWarnings" xml:space="preserve">
@ -711,7 +711,7 @@
<data name="SettingsWarnThreshold" xml:space="preserve">
<value>сколько варнов чтобы потом бан</value>
</data>
<data name="ListWarnTitle" xml:space="preserve">
<data name="ListExecutorWarnsTitle" xml:space="preserve">
<value>хаха, смотри {0}, это все ты заслужил:</value>
</data>
<data name="YouHaveNoWarnings" xml:space="preserve">
@ -762,4 +762,37 @@
<data name="BotCannotWarnMembers" xml:space="preserve">
<value>я не могу ваще никого варить...</value>
</data>
<data name="UserCannotWarnMembers" xml:space="preserve">
<value>тебе нельзя варить шизоидов</value>
</data>
<data name="UserCannotUnwarnMembers" xml:space="preserve">
<value>тебе нельзя разваривать шизоидов</value>
</data>
<data name="UserCannotGetWarnsThemselves" xml:space="preserve">
<value>а ты специально указал себя когда мог этого не делать?</value>
</data>
<data name="UserCannotGetWarnsMembers" xml:space="preserve">
<value>тебе нельзя чекать варны шизоидов</value>
</data>
<data name="UserCannotGetWarnsOwner" xml:space="preserve">
<value>чекать варны админа нельзя</value>
</data>
<data name="UserCannotGetWarnsBot" xml:space="preserve">
<value>чекать варны бота нельзя</value>
</data>
<data name="UserCannotGetWarnsTarget" xml:space="preserve">
<value>чекать варты этого шизика нельзя</value>
</data>
<data name="ListTargetWarnsTitle" xml:space="preserve">
<value>самовары {0}:</value>
</data>
<data name="DescriptionPunishmentType" xml:space="preserve">
<value>тип бана: {0}</value>
</data>
<data name="WarnThresholdExceeded" xml:space="preserve">
<value>мы дошли до лимита варнов. ({0})</value>
</data>
<data name="WarnPunishmentDurationNotSet" xml:space="preserve">
<value>наказание что было установлено хочет установленного WarnPunishmentDuration</value>
</data>
</root>

View file

@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text;
using JetBrains.Annotations;
@ -24,6 +25,7 @@ namespace Octobot.Commands;
[UsedImplicitly]
public class WarnCommandGroup : CommandGroup
{
private readonly AccessControlService _access;
private readonly IDiscordRestChannelAPI _channelApi;
private readonly ICommandContext _context;
private readonly IFeedbackService _feedback;
@ -35,7 +37,7 @@ public class WarnCommandGroup : CommandGroup
public WarnCommandGroup(
ICommandContext context, IDiscordRestChannelAPI channelApi, GuildDataService guildData,
IFeedbackService feedback, IDiscordRestGuildAPI guildApi, IDiscordRestUserAPI userApi,
Utility utility)
Utility utility, AccessControlService access)
{
_context = context;
_channelApi = channelApi;
@ -44,13 +46,14 @@ public class WarnCommandGroup : CommandGroup
_guildApi = guildApi;
_userApi = userApi;
_utility = utility;
_access = access;
}
[Command("warn")]
[DiscordDefaultMemberPermissions(DiscordPermission.KickMembers)]
[DiscordDefaultMemberPermissions(DiscordPermission.ManageMessages)]
[DiscordDefaultDMPermission(false)]
[RequireContext(ChannelContext.Guild)]
[RequireDiscordPermission(DiscordPermission.KickMembers)]
[RequireDiscordPermission(DiscordPermission.ManageMessages)]
[RequireBotDiscordPermissions(DiscordPermission.KickMembers,
DiscordPermission.ModerateMembers, DiscordPermission.BanMembers)]
[Description("Warn user")]
@ -93,7 +96,7 @@ public class WarnCommandGroup : CommandGroup
GuildData data, Snowflake channelId, IUser bot, CancellationToken ct = default)
{
var interactionResult
= await _utility.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "Warn", ct);
= await _access.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "Warn", ct);
if (!interactionResult.IsSuccess)
{
return ResultExtensions.FromError(interactionResult);
@ -110,6 +113,17 @@ public class WarnCommandGroup : CommandGroup
var memberData = data.GetOrCreateMemberData(target.ID);
var warns = memberData.Warns;
var warnThreshold = GuildSettings.WarnsThreshold.Get(data.Settings);
if (warns.Count >= warnThreshold && warnThreshold is not 0)
{
var errorEmbed = new EmbedBuilder()
.WithSmallTitle(string.Format(Messages.WarnThresholdExceeded, warnThreshold), bot)
.WithColour(ColorsList.Red).Build();
return await _feedback.SendContextualEmbedResultAsync(errorEmbed, ct: ct);
}
warns.Add(new Warn
{
WarnedBy = executor.ID.Value,
@ -117,12 +131,10 @@ public class WarnCommandGroup : CommandGroup
Reason = reason
});
var warnsThreshold = GuildSettings.WarnsThreshold.Get(data.Settings);
var builder = new StringBuilder()
.AppendBulletPointLine(string.Format(Messages.DescriptionActionReason, reason))
.AppendBulletPointLine(string.Format(Messages.DescriptionActionWarns,
warnsThreshold is 0 ? warns.Count : $"{warns.Count}/{warnsThreshold}"));
.AppendBulletPointLine(string.Format(Messages.DescriptionWarns,
warnThreshold is 0 ? warns.Count : $"{warns.Count}/{warnThreshold}"));
var title = string.Format(Messages.UserWarned, target.GetTag());
var description = builder.ToString();
@ -144,11 +156,10 @@ public class WarnCommandGroup : CommandGroup
_utility.LogAction(
data.Settings, channelId, executor, title, description, target, ColorsList.Yellow, false, ct);
if (warns.Count >= warnsThreshold &&
if (warns.Count >= warnThreshold &&
GuildSettings.WarnPunishment.Get(data.Settings) is not "off" and not "disable" and not "disabled")
{
warns.Clear();
return await PunishUserAsync(target, guild, data, channelId, bot, CancellationToken);
return await PunishUserAsync(target, guild, data, channelId, bot, warns, CancellationToken);
}
var embed = new EmbedBuilder().WithSmallTitle(
@ -159,42 +170,56 @@ public class WarnCommandGroup : CommandGroup
}
private async Task<Result> PunishUserAsync(IUser target, IGuild guild,
GuildData data, Snowflake channelId, IUser bot, CancellationToken ct)
GuildData data, Snowflake channelId, IUser bot, IList warns, CancellationToken ct)
{
var settings = data.Settings;
var warnPunishment = GuildSettings.WarnPunishment.Get(settings);
var duration = GuildSettings.WarnPunishmentDuration.Get(settings);
if (GuildSettings.WarnPunishment.Get(settings) is "ban"
&& duration != TimeSpan.Zero)
if (warnPunishment is "ban" && duration != TimeSpan.Zero)
{
var banCommandGroup = new BanCommandGroup(_context, _channelApi, _guildData, _feedback, _guildApi, _userApi, _utility);
warns.Clear();
var banCommandGroup = new BanCommandGroup(
_access, _channelApi, _context, _feedback, _guildApi, _guildData, _userApi, _utility);
await banCommandGroup.BanUserAsync(bot, target, Messages.ReceivedTooManyWarnings,
duration, guild, data, channelId, bot, ct);
}
if (GuildSettings.WarnPunishment.Get(settings) is "kick")
if (warnPunishment is "kick")
{
var kickCommandGroup = new KickCommandGroup(_context, _channelApi, _guildData, _feedback, _guildApi, _userApi, _utility);
warns.Clear();
var kickCommandGroup = new KickCommandGroup(
_access, _channelApi, _context, _feedback, _guildApi, _guildData, _userApi, _utility);
await kickCommandGroup.KickUserAsync(bot, target, Messages.ReceivedTooManyWarnings,
guild, channelId, data, bot, ct);
}
if (GuildSettings.WarnPunishment.Get(settings) is "mute"
&& duration != TimeSpan.Zero)
if (warnPunishment is "mute" && duration != TimeSpan.Zero)
{
var muteCommandGroup = new MuteCommandGroup(_context, _guildData, _feedback, _guildApi, _userApi, _utility);
warns.Clear();
var muteCommandGroup = new MuteCommandGroup(
_access, _context, _feedback, _guildApi, _guildData, _userApi, _utility);
await muteCommandGroup.MuteUserAsync(bot, target, Messages.ReceivedTooManyWarnings,
duration, guild.ID, data, channelId, bot, ct);
}
if (warnPunishment is not ("ban" or "mute") || duration != TimeSpan.Zero)
{
return Result.FromSuccess();
}
var errorEmbed = new EmbedBuilder()
.WithSmallTitle(Messages.WarnPunishmentDurationNotSet, bot)
.WithColour(ColorsList.Red).Build();
return await _feedback.SendContextualEmbedResultAsync(errorEmbed, ct: ct);
}
[Command("unwarn")]
[DiscordDefaultMemberPermissions(DiscordPermission.KickMembers)]
[DiscordDefaultMemberPermissions(DiscordPermission.ManageMessages)]
[DiscordDefaultDMPermission(false)]
[RequireContext(ChannelContext.Guild)]
[RequireDiscordPermission(DiscordPermission.KickMembers)]
[RequireDiscordPermission(DiscordPermission.ManageMessages)]
[Description("Remove warns from user")]
[UsedImplicitly]
public async Task<Result> ExecuteUnwarnAsync(
@ -244,7 +269,7 @@ public class WarnCommandGroup : CommandGroup
IGuild guild, GuildData data, Snowflake channelId, IUser bot, CancellationToken ct = default)
{
var interactionResult
= await _utility.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "Unwarn", ct);
= await _access.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "Unwarn", ct);
if (!interactionResult.IsSuccess)
{
return ResultExtensions.FromError(interactionResult);
@ -316,7 +341,7 @@ public class WarnCommandGroup : CommandGroup
IGuild guild, GuildData data, Snowflake channelId, IUser bot, CancellationToken ct = default)
{
var interactionResult
= await _utility.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "Unwarn", ct);
= await _access.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "Unwarn", ct);
if (!interactionResult.IsSuccess)
{
return ResultExtensions.FromError(interactionResult);
@ -377,7 +402,9 @@ public class WarnCommandGroup : CommandGroup
[Ephemeral]
[Description("(Ephemeral) Get current warns")]
[UsedImplicitly]
public async Task<Result> ExecuteListWarnsAsync()
public async Task<Result> ExecuteListWarnsAsync(
[Description("(Moderator-only) Get target's current warns")]
IUser? target = null)
{
if (!_context.TryGetContextIDs(out var guildId, out _, out var executorId))
{
@ -405,10 +432,75 @@ public class WarnCommandGroup : CommandGroup
var data = await _guildData.GetData(guild.ID, CancellationToken);
Messages.Culture = GuildSettings.Language.Get(data.Settings);
return await ListWarnsAsync(executor, data, bot, CancellationToken);
if (target is not null)
{
return await ListTargetWarnsAsync(executor, target, guild, data, bot, CancellationToken);
}
private async Task<Result> ListWarnsAsync(IUser executor, GuildData data, IUser bot, CancellationToken ct = default)
return await ListExecutorWarnsAsync(executor, data, bot, CancellationToken);
}
private async Task<Result> ListTargetWarnsAsync(IUser executor, IUser target, IGuild guild,
GuildData data, IUser bot, CancellationToken ct = default)
{
var interactionResult
= await _access.CheckInteractionsAsync(guild.ID, executor.ID, target.ID, "GetWarns", ct);
if (!interactionResult.IsSuccess)
{
return ResultExtensions.FromError(interactionResult);
}
if (interactionResult.Entity is not null)
{
var errorEmbed = new EmbedBuilder().WithSmallTitle(interactionResult.Entity, bot)
.WithColour(ColorsList.Red).Build();
return await _feedback.SendContextualEmbedResultAsync(errorEmbed, ct: ct);
}
var memberData = data.GetOrCreateMemberData(target.ID);
var warns = memberData.Warns;
if (warns.Count is 0)
{
var failedEmbed = new EmbedBuilder().WithSmallTitle(Messages.UserHasNoWarnings, bot)
.WithColour(ColorsList.Green).Build();
return await _feedback.SendContextualEmbedResultAsync(failedEmbed, ct: ct);
}
var warnThreshold = GuildSettings.WarnsThreshold.Get(data.Settings);
var punishmentType = GuildSettings.WarnPunishment.Get(data.Settings);
var description = new StringBuilder()
.AppendLine(string.Format(Messages.DescriptionWarns,
warnThreshold is 0 ? warns.Count : $"{warns.Count}/{warnThreshold}"));
if (punishmentType is not "off" and not "disable" and not "disabled")
{
description.AppendLine(string.Format(
Messages.DescriptionPunishmentType, Markdown.InlineCode(punishmentType)));
}
var warnCount = 0;
foreach (var warn in warns)
{
warnCount++;
description.Append(warnCount).Append(". ").AppendLine(warn.Reason)
.AppendSubBulletPoint(Messages.IssuedBy).Append(' ').AppendLine(Mention.User(warn.WarnedBy.ToSnowflake()))
.AppendSubBulletPointLine(string.Format(Messages.ReceivedOn, Markdown.Timestamp(warn.At)));
}
var embed = new EmbedBuilder()
.WithSmallTitle(string.Format(Messages.ListTargetWarnsTitle, target.GetTag()), target)
.WithDescription(description.ToString())
.WithColour(ColorsList.Default).Build();
return await _feedback.SendContextualEmbedResultAsync(embed, ct: ct);
}
private async Task<Result> ListExecutorWarnsAsync(IUser executor, GuildData data, IUser bot,
CancellationToken ct = default)
{
var memberData = data.GetOrCreateMemberData(executor.ID);
var warns = memberData.Warns;
@ -421,11 +513,18 @@ public class WarnCommandGroup : CommandGroup
return await _feedback.SendContextualEmbedResultAsync(failedEmbed, ct: ct);
}
var warnsThreshold = GuildSettings.WarnsThreshold.Get(data.Settings);
var warnThreshold = GuildSettings.WarnsThreshold.Get(data.Settings);
var punishmentType = GuildSettings.WarnPunishment.Get(data.Settings);
var description = new StringBuilder()
.AppendLine(string.Format(Messages.DescriptionActionWarns,
warnsThreshold is 0 ? warns.Count : $"{warns.Count}/{warnsThreshold}"));
.AppendLine(string.Format(Messages.DescriptionWarns,
warnThreshold is 0 ? warns.Count : $"{warns.Count}/{warnThreshold}"));
if (punishmentType is not "off" and not "disable" and not "disabled")
{
description.AppendLine(string.Format(
Messages.DescriptionPunishmentType, Markdown.InlineCode(punishmentType)));
}
var warnCount = 0;
foreach (var warn in warns)
@ -437,7 +536,7 @@ public class WarnCommandGroup : CommandGroup
}
var embed = new EmbedBuilder()
.WithSmallTitle(string.Format(Messages.ListWarnTitle, executor.GetTag()), executor)
.WithSmallTitle(string.Format(Messages.ListExecutorWarnsTitle, executor.GetTag()), executor)
.WithDescription(description.ToString())
.WithColour(ColorsList.Default).Build();

View file

@ -1233,10 +1233,10 @@ namespace Octobot {
}
}
internal static string DescriptionActionWarns
internal static string DescriptionWarns
{
get {
return ResourceManager.GetString("DescriptionActionWarns", resourceCulture);
return ResourceManager.GetString("DescriptionWarns", resourceCulture);
}
}
@ -1273,10 +1273,10 @@ namespace Octobot {
}
}
internal static string ListWarnTitle
internal static string ListTargetWarnsTitle
{
get {
return ResourceManager.GetString("ListWarnTitle", resourceCulture);
return ResourceManager.GetString("ListTargetWarnsTitle", resourceCulture);
}
}
@ -1308,80 +1308,32 @@ namespace Octobot {
}
}
internal static string UserCannotWarnBot
internal static string ListExecutorWarnsTitle
{
get {
return ResourceManager.GetString("UserCannotWarnBot", resourceCulture);
return ResourceManager.GetString("ListExecutorWarnsTitle", resourceCulture);
}
}
internal static string UserCannotWarnOwner
internal static string DescriptionPunishmentType
{
get {
return ResourceManager.GetString("UserCannotWarnOwner", resourceCulture);
return ResourceManager.GetString("DescriptionPunishmentType", resourceCulture);
}
}
internal static string UserCannotWarnTarget
internal static string WarnThresholdExceeded
{
get {
return ResourceManager.GetString("UserCannotWarnTarget", resourceCulture);
return ResourceManager.GetString("WarnThresholdExceeded", resourceCulture);
}
}
internal static string UserCannotWarnThemselves
internal static string WarnPunishmentDurationNotSet
{
get {
return ResourceManager.GetString("UserCannotWarnThemselves", resourceCulture);
}
}
internal static string UserCannotUnwarnBot
get
{
get {
return ResourceManager.GetString("UserCannotUnwarnBot", resourceCulture);
}
}
internal static string UserCannotUnwarnOwner
{
get {
return ResourceManager.GetString("UserCannotUnwarnOwner", resourceCulture);
}
}
internal static string UserCannotUnwarnTarget
{
get {
return ResourceManager.GetString("UserCannotUnwarnTarget", resourceCulture);
}
}
internal static string UserCannotUnwarnThemselves
{
get {
return ResourceManager.GetString("UserCannotUnwarnThemselves", resourceCulture);
}
}
internal static string BotCannotWarnTarget
{
get {
return ResourceManager.GetString("BotCannotWarnTarget", resourceCulture);
}
}
internal static string BotCannotWarnMembers
{
get {
return ResourceManager.GetString("BotCannotWarnMembers", resourceCulture);
}
}
internal static string BotCannotUnwarnTarget
{
get {
return ResourceManager.GetString("BotCannotUnwarnTarget", resourceCulture);
return ResourceManager.GetString("WarnPunishmentDurationNotSet", resourceCulture);
}
}
}

View file

@ -116,7 +116,8 @@ public sealed class AccessControlService
{
"Ban" => DiscordPermission.BanMembers,
"Kick" => DiscordPermission.KickMembers,
"Mute" or "Unmute" => DiscordPermission.ModerateMembers,
"Mute" or "Unmute" or "Warn" or "Unwarn" or "GetWarns"
=> DiscordPermission.ModerateMembers,
_ => throw new Exception()
});