mirror of
https://github.com/TeamOctolings/Octobot.git
synced 2025-01-31 09:09:00 +03:00
Reduce method complexity in /ban, /unban and some other commands (#50)
This PR does numerous things to reduce method complexity: - Created an extension method `FeedbackService#SendContextualEmbedResultAsync`, which directly takes a `Result<Embed>` and checks it once in the extension method instead of multiple times in all commands; - Split the command methods for `/ban` and `/unban` into 2 parts: `Execute(Un)Ban` and `(Un)BanUserAsync`. The former will check all the needed results and will pass the outputs into the latter; - Extracted the method for logging an action into Private- and PublicFeedbackChannels. It now resides in UtilityService. Right now, only `/ban` and `/unban` make use of that method; - Created an extension method `Snowflake#EmptyOrEqualTo`, that combines the task of checking if a Snowflake is empty and checking if that Snowflake is equal to another Snowflake. Similar changes will be made to other command groups in future PRs. This is not done here to make the reviewing process easier. Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
This commit is contained in:
parent
c825848d7e
commit
e2bf083189
10 changed files with 186 additions and 186 deletions
|
@ -72,8 +72,7 @@ public class AboutCommandGroup : CommandGroup {
|
|||
.WithColour(ColorsList.Cyan)
|
||||
.WithImageUrl("https://cdn.upload.systems/uploads/JFAaX5vr.png")
|
||||
.Build();
|
||||
if (!embed.IsDefined(out var built)) return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ using Remora.Commands.Attributes;
|
|||
using Remora.Commands.Groups;
|
||||
using Remora.Discord.API.Abstractions.Objects;
|
||||
using Remora.Discord.API.Abstractions.Rest;
|
||||
using Remora.Discord.API.Objects;
|
||||
using Remora.Discord.Commands.Attributes;
|
||||
using Remora.Discord.Commands.Conditions;
|
||||
using Remora.Discord.Commands.Contexts;
|
||||
using Remora.Discord.Commands.Feedback.Services;
|
||||
using Remora.Discord.Extensions.Embeds;
|
||||
using Remora.Discord.Extensions.Formatting;
|
||||
using Remora.Rest.Core;
|
||||
using Remora.Results;
|
||||
|
||||
namespace Boyfriend.Commands;
|
||||
|
@ -57,7 +57,7 @@ public class BanCommandGroup : CommandGroup {
|
|||
/// A feedback sending result which may or may not have succeeded. A successful result does not mean that the user
|
||||
/// was banned and vice-versa.
|
||||
/// </returns>
|
||||
/// <seealso cref="UnbanUserAsync" />
|
||||
/// <seealso cref="ExecuteUnban" />
|
||||
[Command("ban", "бан")]
|
||||
[DiscordDefaultMemberPermissions(DiscordPermission.BanMembers)]
|
||||
[DiscordDefaultDMPermission(false)]
|
||||
|
@ -66,122 +66,95 @@ public class BanCommandGroup : CommandGroup {
|
|||
[RequireBotDiscordPermissions(DiscordPermission.BanMembers)]
|
||||
[Description("Ban user")]
|
||||
[UsedImplicitly]
|
||||
public async Task<Result> BanUserAsync(
|
||||
public async Task<Result> ExecuteBan(
|
||||
[Description("User to ban")] IUser target,
|
||||
[Description("Ban reason")] string reason,
|
||||
[Description("Ban duration")] TimeSpan? duration = null) {
|
||||
if (!_context.TryGetContextIDs(out var guildId, out var channelId, out var userId))
|
||||
return Result.FromError(
|
||||
new ArgumentNullError(nameof(_context), "Unable to retrieve necessary IDs from command context"));
|
||||
|
||||
// The current user's avatar is used when sending error messages
|
||||
var currentUserResult = await _userApi.GetCurrentUserAsync(CancellationToken);
|
||||
if (!currentUserResult.IsDefined(out var currentUser))
|
||||
return Result.FromError(currentUserResult);
|
||||
var userResult = await _userApi.GetUserAsync(userId.Value, CancellationToken);
|
||||
if (!userResult.IsDefined(out var user))
|
||||
return Result.FromError(userResult);
|
||||
var guildResult = await _guildApi.GetGuildAsync(guildId.Value, ct: CancellationToken);
|
||||
if (!guildResult.IsDefined(out var guild))
|
||||
return Result.FromError(guildResult);
|
||||
|
||||
var data = await _dataService.GetData(guildId.Value, CancellationToken);
|
||||
return await BanUserAsync(target, reason, duration, guild, channelId.Value, user, currentUser);
|
||||
}
|
||||
|
||||
private async Task<Result> BanUserAsync(
|
||||
IUser target, string reason, TimeSpan? duration, IGuild guild, Snowflake channelId,
|
||||
IUser user, IUser currentUser) {
|
||||
var data = await _dataService.GetData(guild.ID, CancellationToken);
|
||||
var cfg = data.Settings;
|
||||
Messages.Culture = GuildSettings.Language.Get(cfg);
|
||||
|
||||
var existingBanResult = await _guildApi.GetGuildBanAsync(guildId.Value, target.ID, CancellationToken);
|
||||
var existingBanResult = await _guildApi.GetGuildBanAsync(guild.ID, target.ID, CancellationToken);
|
||||
if (existingBanResult.IsDefined()) {
|
||||
var embed = new EmbedBuilder().WithSmallTitle(Messages.UserAlreadyBanned, currentUser)
|
||||
var failedEmbed = new EmbedBuilder().WithSmallTitle(Messages.UserAlreadyBanned, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
|
||||
if (!embed.IsDefined(out var alreadyBuilt))
|
||||
return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(alreadyBuilt, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(failedEmbed, CancellationToken);
|
||||
}
|
||||
|
||||
var interactionResult
|
||||
= await _utility.CheckInteractionsAsync(guildId.Value, userId.Value, target.ID, "Ban", CancellationToken);
|
||||
= await _utility.CheckInteractionsAsync(guild.ID, user.ID, target.ID, "Ban", CancellationToken);
|
||||
if (!interactionResult.IsSuccess)
|
||||
return Result.FromError(interactionResult);
|
||||
|
||||
Result<Embed> responseEmbed;
|
||||
if (interactionResult.Entity is not null) {
|
||||
responseEmbed = new EmbedBuilder().WithSmallTitle(interactionResult.Entity, currentUser)
|
||||
var errorEmbed = new EmbedBuilder().WithSmallTitle(interactionResult.Entity, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
} else {
|
||||
var userResult = await _userApi.GetUserAsync(userId.Value, CancellationToken);
|
||||
if (!userResult.IsDefined(out var user))
|
||||
return Result.FromError(userResult);
|
||||
|
||||
var builder = new StringBuilder().AppendLine(string.Format(Messages.DescriptionActionReason, reason));
|
||||
if (duration is not null)
|
||||
builder.Append(
|
||||
string.Format(
|
||||
Messages.DescriptionActionExpiresAt,
|
||||
Markdown.Timestamp(DateTimeOffset.UtcNow.Add(duration.Value))));
|
||||
var description = builder.ToString();
|
||||
|
||||
var dmChannelResult = await _userApi.CreateDMAsync(target.ID, CancellationToken);
|
||||
if (dmChannelResult.IsDefined(out var dmChannel)) {
|
||||
var guildResult = await _guildApi.GetGuildAsync(guildId.Value, ct: CancellationToken);
|
||||
if (!guildResult.IsDefined(out var guild))
|
||||
return Result.FromError(guildResult);
|
||||
|
||||
var dmEmbed = new EmbedBuilder().WithGuildTitle(guild)
|
||||
.WithTitle(Messages.YouWereBanned)
|
||||
.WithDescription(description)
|
||||
.WithActionFooter(user)
|
||||
.WithCurrentTimestamp()
|
||||
.WithColour(ColorsList.Red)
|
||||
.Build();
|
||||
|
||||
if (!dmEmbed.IsDefined(out var dmBuilt))
|
||||
return Result.FromError(dmEmbed);
|
||||
await _channelApi.CreateMessageAsync(dmChannel.ID, embeds: new[] { dmBuilt }, ct: CancellationToken);
|
||||
}
|
||||
|
||||
var banResult = await _guildApi.CreateGuildBanAsync(
|
||||
guildId.Value, target.ID, reason: $"({user.GetTag()}) {reason}".EncodeHeader(),
|
||||
ct: CancellationToken);
|
||||
if (!banResult.IsSuccess)
|
||||
return Result.FromError(banResult.Error);
|
||||
var memberData = data.GetMemberData(target.ID);
|
||||
memberData.BannedUntil
|
||||
= duration is not null ? DateTimeOffset.UtcNow.Add(duration.Value) : DateTimeOffset.MaxValue;
|
||||
memberData.Roles.Clear();
|
||||
|
||||
responseEmbed = new EmbedBuilder().WithSmallTitle(
|
||||
string.Format(Messages.UserBanned, target.GetTag()), target)
|
||||
.WithColour(ColorsList.Green).Build();
|
||||
|
||||
if ((!GuildSettings.PublicFeedbackChannel.Get(cfg).Empty()
|
||||
&& GuildSettings.PublicFeedbackChannel.Get(cfg) != channelId.Value)
|
||||
|| (!GuildSettings.PrivateFeedbackChannel.Get(cfg).Empty()
|
||||
&& GuildSettings.PrivateFeedbackChannel.Get(cfg) != channelId.Value)) {
|
||||
var logEmbed = new EmbedBuilder().WithSmallTitle(
|
||||
string.Format(Messages.UserBanned, target.GetTag()), target)
|
||||
.WithDescription(description)
|
||||
.WithActionFooter(user)
|
||||
.WithCurrentTimestamp()
|
||||
.WithColour(ColorsList.Red)
|
||||
.Build();
|
||||
|
||||
if (!logEmbed.IsDefined(out var logBuilt))
|
||||
return Result.FromError(logEmbed);
|
||||
|
||||
var builtArray = new[] { logBuilt };
|
||||
// Not awaiting to reduce response time
|
||||
if (GuildSettings.PublicFeedbackChannel.Get(cfg) != channelId.Value)
|
||||
_ = _channelApi.CreateMessageAsync(
|
||||
GuildSettings.PublicFeedbackChannel.Get(cfg), embeds: builtArray,
|
||||
ct: CancellationToken);
|
||||
if (GuildSettings.PrivateFeedbackChannel.Get(cfg) != GuildSettings.PublicFeedbackChannel.Get(cfg)
|
||||
&& GuildSettings.PrivateFeedbackChannel.Get(cfg) != channelId.Value)
|
||||
_ = _channelApi.CreateMessageAsync(
|
||||
GuildSettings.PrivateFeedbackChannel.Get(cfg), embeds: builtArray,
|
||||
ct: CancellationToken);
|
||||
}
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(errorEmbed, CancellationToken);
|
||||
}
|
||||
|
||||
if (!responseEmbed.IsDefined(out var built))
|
||||
return Result.FromError(responseEmbed);
|
||||
var builder = new StringBuilder().AppendLine(string.Format(Messages.DescriptionActionReason, reason));
|
||||
if (duration is not null)
|
||||
builder.Append(
|
||||
string.Format(
|
||||
Messages.DescriptionActionExpiresAt,
|
||||
Markdown.Timestamp(DateTimeOffset.UtcNow.Add(duration.Value))));
|
||||
var title = string.Format(Messages.UserBanned, target.GetTag());
|
||||
var description = builder.ToString();
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
var dmChannelResult = await _userApi.CreateDMAsync(target.ID, CancellationToken);
|
||||
if (dmChannelResult.IsDefined(out var dmChannel)) {
|
||||
var dmEmbed = new EmbedBuilder().WithGuildTitle(guild)
|
||||
.WithTitle(Messages.YouWereBanned)
|
||||
.WithDescription(description)
|
||||
.WithActionFooter(user)
|
||||
.WithCurrentTimestamp()
|
||||
.WithColour(ColorsList.Red)
|
||||
.Build();
|
||||
|
||||
if (!dmEmbed.IsDefined(out var dmBuilt))
|
||||
return Result.FromError(dmEmbed);
|
||||
await _channelApi.CreateMessageAsync(dmChannel.ID, embeds: new[] { dmBuilt }, ct: CancellationToken);
|
||||
}
|
||||
|
||||
var banResult = await _guildApi.CreateGuildBanAsync(
|
||||
guild.ID, target.ID, reason: $"({user.GetTag()}) {reason}".EncodeHeader(),
|
||||
ct: CancellationToken);
|
||||
if (!banResult.IsSuccess)
|
||||
return Result.FromError(banResult.Error);
|
||||
var memberData = data.GetMemberData(target.ID);
|
||||
memberData.BannedUntil
|
||||
= duration is not null ? DateTimeOffset.UtcNow.Add(duration.Value) : DateTimeOffset.MaxValue;
|
||||
memberData.Roles.Clear();
|
||||
|
||||
var embed = new EmbedBuilder().WithSmallTitle(
|
||||
title, target)
|
||||
.WithColour(ColorsList.Green).Build();
|
||||
|
||||
_utility.LogActionAsync(cfg, channelId, title, target, description, user, CancellationToken);
|
||||
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -196,7 +169,7 @@ public class BanCommandGroup : CommandGroup {
|
|||
/// A feedback sending result which may or may not have succeeded. A successful result does not mean that the user
|
||||
/// was unbanned and vice-versa.
|
||||
/// </returns>
|
||||
/// <seealso cref="BanUserAsync" />
|
||||
/// <seealso cref="ExecuteBan" />
|
||||
/// <seealso cref="GuildUpdateService.TickGuildAsync"/>
|
||||
[Command("unban")]
|
||||
[DiscordDefaultMemberPermissions(DiscordPermission.BanMembers)]
|
||||
|
@ -206,79 +179,53 @@ public class BanCommandGroup : CommandGroup {
|
|||
[RequireBotDiscordPermissions(DiscordPermission.BanMembers)]
|
||||
[Description("Unban user")]
|
||||
[UsedImplicitly]
|
||||
public async Task<Result> UnbanUserAsync(
|
||||
public async Task<Result> ExecuteUnban(
|
||||
[Description("User to unban")] IUser target,
|
||||
[Description("Unban reason")] string reason) {
|
||||
if (!_context.TryGetContextIDs(out var guildId, out var channelId, out var userId))
|
||||
return Result.FromError(
|
||||
new ArgumentNullError(nameof(_context), "Unable to retrieve necessary IDs from command context"));
|
||||
|
||||
// The current user's avatar is used when sending error messages
|
||||
var currentUserResult = await _userApi.GetCurrentUserAsync(CancellationToken);
|
||||
if (!currentUserResult.IsDefined(out var currentUser))
|
||||
return Result.FromError(currentUserResult);
|
||||
|
||||
var cfg = await _dataService.GetSettings(guildId.Value, CancellationToken);
|
||||
Messages.Culture = GuildSettings.Language.Get(cfg);
|
||||
|
||||
var existingBanResult = await _guildApi.GetGuildBanAsync(guildId.Value, target.ID, CancellationToken);
|
||||
if (!existingBanResult.IsDefined()) {
|
||||
var embed = new EmbedBuilder().WithSmallTitle(Messages.UserNotBanned, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
|
||||
if (!embed.IsDefined(out var alreadyBuilt))
|
||||
return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(alreadyBuilt, ct: CancellationToken);
|
||||
}
|
||||
|
||||
// Needed to get the tag and avatar
|
||||
var userResult = await _userApi.GetUserAsync(userId.Value, CancellationToken);
|
||||
if (!userResult.IsDefined(out var user))
|
||||
return Result.FromError(userResult);
|
||||
|
||||
return await UnbanUserAsync(target, reason, guildId.Value, channelId.Value, user, currentUser);
|
||||
}
|
||||
|
||||
private async Task<Result> UnbanUserAsync(
|
||||
IUser target, string reason, Snowflake guildId, Snowflake channelId, IUser user, IUser currentUser) {
|
||||
var cfg = await _dataService.GetSettings(guildId, CancellationToken);
|
||||
Messages.Culture = GuildSettings.Language.Get(cfg);
|
||||
|
||||
var existingBanResult = await _guildApi.GetGuildBanAsync(guildId, target.ID, CancellationToken);
|
||||
if (!existingBanResult.IsDefined()) {
|
||||
var errorEmbed = new EmbedBuilder().WithSmallTitle(Messages.UserNotBanned, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(errorEmbed, CancellationToken);
|
||||
}
|
||||
|
||||
var unbanResult = await _guildApi.RemoveGuildBanAsync(
|
||||
guildId.Value, target.ID, $"({user.GetTag()}) {reason}".EncodeHeader(),
|
||||
guildId, target.ID, $"({user.GetTag()}) {reason}".EncodeHeader(),
|
||||
ct: CancellationToken);
|
||||
if (!unbanResult.IsSuccess)
|
||||
return Result.FromError(unbanResult.Error);
|
||||
|
||||
var responseEmbed = new EmbedBuilder().WithSmallTitle(
|
||||
var embed = new EmbedBuilder().WithSmallTitle(
|
||||
string.Format(Messages.UserUnbanned, target.GetTag()), target)
|
||||
.WithColour(ColorsList.Green).Build();
|
||||
|
||||
if ((!GuildSettings.PublicFeedbackChannel.Get(cfg).Empty()
|
||||
&& GuildSettings.PublicFeedbackChannel.Get(cfg) != channelId.Value)
|
||||
|| (!GuildSettings.PrivateFeedbackChannel.Get(cfg).Empty()
|
||||
&& GuildSettings.PrivateFeedbackChannel.Get(cfg) != channelId.Value)) {
|
||||
var logEmbed = new EmbedBuilder().WithSmallTitle(
|
||||
string.Format(Messages.UserUnbanned, target.GetTag()), target)
|
||||
.WithDescription(string.Format(Messages.DescriptionActionReason, reason))
|
||||
.WithActionFooter(user)
|
||||
.WithCurrentTimestamp()
|
||||
.WithColour(ColorsList.Green)
|
||||
.Build();
|
||||
var title = string.Format(Messages.UserUnbanned, target.GetTag());
|
||||
var description = string.Format(Messages.DescriptionActionReason, reason);
|
||||
var logResult = _utility.LogActionAsync(cfg, channelId, title, target, description, user, CancellationToken);
|
||||
if (!logResult.IsSuccess)
|
||||
return Result.FromError(logResult.Error);
|
||||
|
||||
if (!logEmbed.IsDefined(out var logBuilt))
|
||||
return Result.FromError(logEmbed);
|
||||
|
||||
var builtArray = new[] { logBuilt };
|
||||
|
||||
// Not awaiting to reduce response time
|
||||
if (GuildSettings.PublicFeedbackChannel.Get(cfg) != channelId.Value)
|
||||
_ = _channelApi.CreateMessageAsync(
|
||||
GuildSettings.PublicFeedbackChannel.Get(cfg), embeds: builtArray,
|
||||
ct: CancellationToken);
|
||||
if (GuildSettings.PrivateFeedbackChannel.Get(cfg) != GuildSettings.PublicFeedbackChannel.Get(cfg)
|
||||
&& GuildSettings.PrivateFeedbackChannel.Get(cfg) != channelId.Value)
|
||||
_ = _channelApi.CreateMessageAsync(
|
||||
GuildSettings.PrivateFeedbackChannel.Get(cfg), embeds: builtArray,
|
||||
ct: CancellationToken);
|
||||
}
|
||||
|
||||
if (!responseEmbed.IsDefined(out var built))
|
||||
return Result.FromError(responseEmbed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,8 +117,7 @@ public class ClearCommandGroup : CommandGroup {
|
|||
|
||||
var embed = new EmbedBuilder().WithSmallTitle(title, currentUser)
|
||||
.WithColour(ColorsList.Green).Build();
|
||||
if (!embed.IsDefined(out var built)) return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,10 +83,7 @@ public class KickCommandGroup : CommandGroup {
|
|||
var embed = new EmbedBuilder().WithSmallTitle(Messages.UserNotFoundShort, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
|
||||
if (!embed.IsDefined(out var alreadyBuilt))
|
||||
return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(alreadyBuilt, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
|
||||
var interactionResult
|
||||
|
@ -162,9 +159,6 @@ public class KickCommandGroup : CommandGroup {
|
|||
}
|
||||
}
|
||||
|
||||
if (!responseEmbed.IsDefined(out var built))
|
||||
return Result.FromError(responseEmbed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(responseEmbed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,10 +84,7 @@ public class MuteCommandGroup : CommandGroup {
|
|||
var embed = new EmbedBuilder().WithSmallTitle(Messages.UserNotFoundShort, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
|
||||
if (!embed.IsDefined(out var alreadyBuilt))
|
||||
return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(alreadyBuilt, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
|
||||
var interactionResult
|
||||
|
@ -154,10 +151,7 @@ public class MuteCommandGroup : CommandGroup {
|
|||
}
|
||||
}
|
||||
|
||||
if (!responseEmbed.IsDefined(out var built))
|
||||
return Result.FromError(responseEmbed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(responseEmbed, CancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -202,10 +196,7 @@ public class MuteCommandGroup : CommandGroup {
|
|||
var embed = new EmbedBuilder().WithSmallTitle(Messages.UserNotFoundShort, currentUser)
|
||||
.WithColour(ColorsList.Red).Build();
|
||||
|
||||
if (!embed.IsDefined(out var alreadyBuilt))
|
||||
return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(alreadyBuilt, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
|
||||
var interactionResult
|
||||
|
@ -258,9 +249,6 @@ public class MuteCommandGroup : CommandGroup {
|
|||
ct: CancellationToken);
|
||||
}
|
||||
|
||||
if (!responseEmbed.IsDefined(out var built))
|
||||
return Result.FromError(responseEmbed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(responseEmbed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,8 +77,7 @@ public class PingCommandGroup : CommandGroup {
|
|||
.WithColour(latency < 250 ? ColorsList.Green : latency < 500 ? ColorsList.Yellow : ColorsList.Red)
|
||||
.WithCurrentTimestamp()
|
||||
.Build();
|
||||
if (!embed.IsDefined(out var built)) return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,9 +71,6 @@ public class RemindCommandGroup : CommandGroup {
|
|||
.WithColour(ColorsList.Green)
|
||||
.Build();
|
||||
|
||||
if (!embed.IsDefined(out var built))
|
||||
return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,9 +90,8 @@ public class SettingsCommandGroup : CommandGroup {
|
|||
.WithDescription(builder.ToString())
|
||||
.WithColour(ColorsList.Default)
|
||||
.Build();
|
||||
if (!embed.IsDefined(out var built)) return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -132,9 +131,8 @@ public class SettingsCommandGroup : CommandGroup {
|
|||
.WithDescription(setResult.Error.Message)
|
||||
.WithColour(ColorsList.Red)
|
||||
.Build();
|
||||
if (!failedEmbed.IsDefined(out var failedBuilt)) return Result.FromError(failedEmbed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(failedBuilt, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(failedEmbed, CancellationToken);
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
|
@ -147,8 +145,7 @@ public class SettingsCommandGroup : CommandGroup {
|
|||
.WithDescription(builder.ToString())
|
||||
.WithColour(ColorsList.Green)
|
||||
.Build();
|
||||
if (!embed.IsDefined(out var built)) return Result.FromError(embed);
|
||||
|
||||
return (Result)await _feedbackService.SendContextualEmbedAsync(built, ct: CancellationToken);
|
||||
return await _feedbackService.SendContextualEmbedResultAsync(embed, CancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ using Remora.Discord.API.Abstractions.Objects;
|
|||
using Remora.Discord.API.Objects;
|
||||
using Remora.Discord.Commands.Contexts;
|
||||
using Remora.Discord.Commands.Extensions;
|
||||
using Remora.Discord.Commands.Feedback.Services;
|
||||
using Remora.Discord.Extensions.Embeds;
|
||||
using Remora.Discord.Extensions.Formatting;
|
||||
using Remora.Rest.Core;
|
||||
using Remora.Results;
|
||||
|
||||
namespace Boyfriend;
|
||||
|
||||
|
@ -51,10 +53,9 @@ public static class Extensions {
|
|||
/// <param name="builder">The builder to add the small title to.</param>
|
||||
/// <param name="text">The text of the small title.</param>
|
||||
/// <param name="avatarSource">The user whose avatar to use in the small title.</param>
|
||||
/// <param name="url">The URL that will be opened if a user clicks on the small title.</param>
|
||||
/// <returns>The builder with the added small title in the author field.</returns>
|
||||
public static EmbedBuilder WithSmallTitle(
|
||||
this EmbedBuilder builder, string text, IUser? avatarSource = null, string? url = default) {
|
||||
this EmbedBuilder builder, string text, IUser? avatarSource = null) {
|
||||
Uri? avatarUrl = null;
|
||||
if (avatarSource is not null) {
|
||||
var avatarUrlResult = CDN.GetUserAvatarUrl(avatarSource, imageSize: 256);
|
||||
|
@ -64,7 +65,7 @@ public static class Extensions {
|
|||
: CDN.GetDefaultUserAvatarUrl(avatarSource, imageSize: 256).Entity;
|
||||
}
|
||||
|
||||
builder.Author = new EmbedAuthorBuilder(text, url, avatarUrl?.AbsoluteUri);
|
||||
builder.Author = new EmbedAuthorBuilder(text, iconUrl: avatarUrl?.AbsoluteUri);
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -191,7 +192,35 @@ public static class Extensions {
|
|||
&& context.TryGetUserID(out userId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether this Snowflake has any value set.
|
||||
/// </summary>
|
||||
/// <param name="snowflake">The Snowflake to check.</param>
|
||||
/// <returns>true if the Snowflake has no value set or it's set to 0, false otherwise.</returns>
|
||||
public static bool Empty(this Snowflake snowflake) {
|
||||
return snowflake.Value is 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether this snowflake is empty (see <see cref="Empty" />) or it's equal to
|
||||
/// <paramref name="anotherSnowflake" />
|
||||
/// </summary>
|
||||
/// <param name="snowflake">The Snowflake to check for emptiness</param>
|
||||
/// <param name="anotherSnowflake">The Snowflake to check for equality with <paramref name="snowflake" />.</param>
|
||||
/// <returns>
|
||||
/// true if <paramref name="snowflake" /> is empty or is equal to <paramref name="anotherSnowflake" />, false
|
||||
/// otherwise.
|
||||
/// </returns>
|
||||
/// <seealso cref="Empty" />
|
||||
public static bool EmptyOrEqualTo(this Snowflake snowflake, Snowflake anotherSnowflake) {
|
||||
return snowflake.Empty() || snowflake == anotherSnowflake;
|
||||
}
|
||||
|
||||
public static async Task<Result> SendContextualEmbedResultAsync(
|
||||
this FeedbackService feedback, Result<Embed> embedResult, CancellationToken ct = default) {
|
||||
if (!embedResult.IsDefined(out var embed))
|
||||
return Result.FromError(embedResult);
|
||||
|
||||
return (Result)await feedback.SendContextualEmbedAsync(embed, ct: ct);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using Boyfriend.Data;
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using Remora.Discord.API.Abstractions.Objects;
|
||||
using Remora.Discord.API.Abstractions.Rest;
|
||||
using Remora.Discord.Extensions.Embeds;
|
||||
using Remora.Discord.Extensions.Formatting;
|
||||
using Remora.Rest.Core;
|
||||
using Remora.Results;
|
||||
|
@ -15,15 +16,18 @@ namespace Boyfriend.Services;
|
|||
/// of some Discord APIs.
|
||||
/// </summary>
|
||||
public class UtilityService : IHostedService {
|
||||
private readonly IDiscordRestChannelAPI _channelApi;
|
||||
private readonly IDiscordRestGuildScheduledEventAPI _eventApi;
|
||||
private readonly IDiscordRestGuildAPI _guildApi;
|
||||
private readonly IDiscordRestUserAPI _userApi;
|
||||
|
||||
public UtilityService(
|
||||
IDiscordRestGuildAPI guildApi, IDiscordRestUserAPI userApi, IDiscordRestGuildScheduledEventAPI eventApi) {
|
||||
IDiscordRestChannelAPI channelApi, IDiscordRestGuildScheduledEventAPI eventApi, IDiscordRestGuildAPI guildApi,
|
||||
IDiscordRestUserAPI userApi) {
|
||||
_channelApi = channelApi;
|
||||
_eventApi = eventApi;
|
||||
_guildApi = guildApi;
|
||||
_userApi = userApi;
|
||||
_eventApi = eventApi;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken ct) {
|
||||
|
@ -132,4 +136,51 @@ public class UtilityService : IHostedService {
|
|||
.Aggregate(builder, (current, user) => current.Append($"{Mention.User(user.User)} "));
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an action in the <see cref="GuildSettings.PublicFeedbackChannel" /> and
|
||||
/// <see cref="GuildSettings.PrivateFeedbackChannel" />.
|
||||
/// </summary>
|
||||
/// <param name="cfg">The guild configuration.</param>
|
||||
/// <param name="channelId">The ID of the channel where the action was executed.</param>
|
||||
/// <param name="title">The title for the embed.</param>
|
||||
/// <param name="avatar">The user whose avatar will be displayed next to the <paramref name="title" /> of the embed.</param>
|
||||
/// <param name="description">The description of the embed.</param>
|
||||
/// <param name="user">The user who performed the action.</param>
|
||||
/// <param name="ct">The cancellation token for this operation.</param>
|
||||
/// <returns></returns>
|
||||
public Result LogActionAsync(
|
||||
JsonNode cfg, Snowflake channelId, string title, IUser avatar, string description,
|
||||
IUser user, CancellationToken ct = default) {
|
||||
var publicChannel = GuildSettings.PublicFeedbackChannel.Get(cfg);
|
||||
var privateChannel = GuildSettings.PrivateFeedbackChannel.Get(cfg);
|
||||
if (GuildSettings.PublicFeedbackChannel.Get(cfg).EmptyOrEqualTo(channelId)
|
||||
&& GuildSettings.PrivateFeedbackChannel.Get(cfg).EmptyOrEqualTo(channelId))
|
||||
return Result.FromSuccess();
|
||||
|
||||
var logEmbed = new EmbedBuilder().WithSmallTitle(title, avatar)
|
||||
.WithDescription(description)
|
||||
.WithActionFooter(user)
|
||||
.WithCurrentTimestamp()
|
||||
.WithColour(ColorsList.Green)
|
||||
.Build();
|
||||
|
||||
if (!logEmbed.IsDefined(out var logBuilt))
|
||||
return Result.FromError(logEmbed);
|
||||
|
||||
var builtArray = new[] { logBuilt };
|
||||
|
||||
// Not awaiting to reduce response time
|
||||
if (publicChannel != channelId.Value)
|
||||
_ = _channelApi.CreateMessageAsync(
|
||||
publicChannel, embeds: builtArray,
|
||||
ct: ct);
|
||||
if (privateChannel != publicChannel
|
||||
&& privateChannel != channelId.Value)
|
||||
_ = _channelApi.CreateMessageAsync(
|
||||
privateChannel, embeds: builtArray,
|
||||
ct: ct);
|
||||
|
||||
return Result.FromSuccess();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue