diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2d7e30e..870ada6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.4.0] - 2023-07-23
+
+### Added
+
+- Add new ACCEPTED suggestion status.
+
+### Changed
+
+- `/suggestion implement` and `/suggestion reject` combined to `/suggestion setstatus`.
+
## [1.3.2] - 2023-07-22
### Added
diff --git a/SuggestionBot/Commands/SuggestionCommand.Reject.cs b/SuggestionBot/Commands/SuggestionCommand.Reject.cs
deleted file mode 100644
index a6587e5..0000000
--- a/SuggestionBot/Commands/SuggestionCommand.Reject.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using DSharpPlus.Entities;
-using DSharpPlus.SlashCommands;
-using SuggestionBot.AutocompleteProviders;
-using SuggestionBot.Data;
-
-namespace SuggestionBot.Commands;
-
-internal sealed partial class SuggestionCommand
-{
- [SlashCommand("reject", "Rejects a suggestion.", false)]
- public async Task RejectAsync(InteractionContext context,
- [Option("suggestion", "The suggestion to reject."), Autocomplete(typeof(SuggestionAutocompleteProvider))]
- string query)
- {
- var response = new DiscordInteractionResponseBuilder();
-
- if (!TryGetSuggestion(context.Guild, query, out Suggestion? suggestion))
- {
- response.AsEphemeral();
- response.AddEmbed(CreateNotFoundEmbed(query));
- await context.CreateResponseAsync(ResponseType, response).ConfigureAwait(false);
- return;
- }
-
- var embed = new DiscordEmbedBuilder();
- if (_suggestionService.Reject(suggestion, context.Member))
- {
- embed.WithColor(DiscordColor.Orange);
- embed.WithTitle("Suggestion Rejected");
- embed.WithDescription($"The suggestion with the ID {suggestion.Id} has been marked as REJECTED.");
- }
- else
- {
- embed.WithColor(DiscordColor.Orange);
- embed.WithTitle("Suggestion Unchanged");
- embed.WithDescription($"The suggestion with the ID {suggestion.Id} was already rejected. " +
- "No changes were made.");
- }
-
- response.AddEmbed(embed);
- await context.CreateResponseAsync(ResponseType, response).ConfigureAwait(false);
- }
-}
diff --git a/SuggestionBot/Commands/SuggestionCommand.Implement.cs b/SuggestionBot/Commands/SuggestionCommand.SetStatus.cs
similarity index 61%
rename from SuggestionBot/Commands/SuggestionCommand.Implement.cs
rename to SuggestionBot/Commands/SuggestionCommand.SetStatus.cs
index df0383e..e4e720c 100644
--- a/SuggestionBot/Commands/SuggestionCommand.Implement.cs
+++ b/SuggestionBot/Commands/SuggestionCommand.SetStatus.cs
@@ -1,5 +1,6 @@
using DSharpPlus.Entities;
using DSharpPlus.SlashCommands;
+using Humanizer;
using SuggestionBot.AutocompleteProviders;
using SuggestionBot.Data;
@@ -7,10 +8,13 @@ namespace SuggestionBot.Commands;
internal sealed partial class SuggestionCommand
{
- [SlashCommand("implement", "Implements a suggestion.", false)]
- public async Task ImplementAsync(InteractionContext context,
- [Option("suggestion", "The suggestion to implement."), Autocomplete(typeof(SuggestionAutocompleteProvider))]
- string query)
+ [SlashCommand("setstatus", "Sets a new status for a suggestion.", false)]
+ public async Task SetStatusAsync(InteractionContext context,
+ [Option("suggestion", "The suggestion whose status to change.")]
+ [Autocomplete(typeof(SuggestionAutocompleteProvider))]
+ string query,
+ [Option("status", "The new status of the suggestion.")]
+ SuggestionStatus status)
{
var response = new DiscordInteractionResponseBuilder();
@@ -23,17 +27,19 @@ public async Task ImplementAsync(InteractionContext context,
}
var embed = new DiscordEmbedBuilder();
- if (_suggestionService.Implement(suggestion, context.Member))
+ string humanizedStatus = status.Humanize(LetterCasing.AllCaps);
+
+ if (_suggestionService.SetStatus(suggestion, status, context.Member))
{
embed.WithColor(DiscordColor.Orange);
- embed.WithTitle("Suggestion Implemented");
- embed.WithDescription($"The suggestion with the ID {suggestion.Id} has been marked as IMPLEMENTED.");
+ embed.WithTitle("Suggestion Status Changed");
+ embed.WithDescription($"The suggestion with the ID {suggestion.Id} has been marked as {humanizedStatus}.");
}
else
{
embed.WithColor(DiscordColor.Orange);
embed.WithTitle("Suggestion Unchanged");
- embed.WithDescription($"The suggestion with the ID {suggestion.Id} was already implemented. " +
+ embed.WithDescription($"The suggestion with the ID {suggestion.Id} was already {humanizedStatus}. " +
"No changes were made.");
}
diff --git a/SuggestionBot/Configuration/GuildConfiguration.cs b/SuggestionBot/Configuration/GuildConfiguration.cs
index 3c93b19..4c1a62c 100644
--- a/SuggestionBot/Configuration/GuildConfiguration.cs
+++ b/SuggestionBot/Configuration/GuildConfiguration.cs
@@ -5,6 +5,12 @@
///
public sealed class GuildConfiguration
{
+ ///
+ /// Gets or sets the embed color for accepted suggestions.
+ ///
+ /// The embed color for accepted suggestions.
+ public int AcceptedColor { get; set; } = 0x00FF00;
+
///
/// Gets or sets the cooldown for posting suggestions.
///
diff --git a/SuggestionBot/Data/SuggestionStatus.cs b/SuggestionBot/Data/SuggestionStatus.cs
index 8ce56e0..9dbfd20 100644
--- a/SuggestionBot/Data/SuggestionStatus.cs
+++ b/SuggestionBot/Data/SuggestionStatus.cs
@@ -7,5 +7,6 @@ public enum SuggestionStatus
{
Suggested,
Rejected,
- Implemented
+ Implemented,
+ Accepted
}
diff --git a/SuggestionBot/Services/SuggestionService.cs b/SuggestionBot/Services/SuggestionService.cs
index 7f7ddae..ceae1f6 100644
--- a/SuggestionBot/Services/SuggestionService.cs
+++ b/SuggestionBot/Services/SuggestionService.cs
@@ -74,6 +74,7 @@ public DiscordEmbed CreatePrivateEmbed(Suggestion suggestion)
SuggestionStatus.Suggested => "🗳️",
SuggestionStatus.Rejected => "❌",
SuggestionStatus.Implemented => "✅",
+ SuggestionStatus.Accepted => "✅",
_ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
};
@@ -89,6 +90,7 @@ public DiscordEmbed CreatePrivateEmbed(Suggestion suggestion)
SuggestionStatus.Suggested => configuration.SuggestedColor,
SuggestionStatus.Rejected => configuration.RejectedColor,
SuggestionStatus.Implemented => configuration.ImplementedColor,
+ SuggestionStatus.Accepted => configuration.AcceptedColor,
_ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
});
@@ -136,6 +138,7 @@ public DiscordEmbed CreatePublicEmbed(Suggestion suggestion)
SuggestionStatus.Suggested => "🗳️",
SuggestionStatus.Rejected => "❌",
SuggestionStatus.Implemented => "✅",
+ SuggestionStatus.Accepted => "✅",
_ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
};
@@ -152,6 +155,7 @@ public DiscordEmbed CreatePublicEmbed(Suggestion suggestion)
SuggestionStatus.Suggested => configuration.SuggestedColor,
SuggestionStatus.Rejected => configuration.RejectedColor,
SuggestionStatus.Implemented => configuration.ImplementedColor,
+ SuggestionStatus.Accepted => configuration.AcceptedColor,
_ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
});
@@ -317,42 +321,6 @@ public Uri GetSuggestionLink(Suggestion suggestion)
return new Uri($"https://discord.com/channels/{guildId}/{configuration?.SuggestionChannel}/{messageId}");
}
- ///
- /// Marks a suggestion as implemented, and optionally updates the remarks for the implementation.
- ///
- /// The suggestion to update.
- /// The staff member who implemented the suggestion.
- /// if the status was updated; otherwise, .
- ///
- /// is .
- /// -or-
- /// is .
- ///
- public bool Implement(Suggestion suggestion, DiscordMember staffMember)
- {
- if (suggestion is null)
- {
- throw new ArgumentNullException(nameof(suggestion));
- }
-
- if (staffMember is null)
- {
- throw new ArgumentNullException(nameof(staffMember));
- }
-
- if (!SetStatus(suggestion, SuggestionStatus.Implemented, staffMember))
- {
- return false;
- }
-
- _logger.LogInformation("{StaffMember} marked suggestion {Id} as IMPLEMENTED", staffMember, suggestion.Id);
-
- using SuggestionContext context = _contextFactory.CreateDbContext();
- context.Suggestions.Update(suggestion);
- context.SaveChanges();
- return true;
- }
-
///
/// Posts a suggestion to the suggestion channel of the guild in which it was made.
///
@@ -396,42 +364,6 @@ public bool Implement(Suggestion suggestion, DiscordMember staffMember)
return message;
}
- ///
- /// Marks a suggestion as rejected, and updates the reason for the rejection if one is provided.
- ///
- /// The suggestion to update.
- /// The staff member who rejected the suggestion.
- /// if the status was updated; otherwise, .
- ///
- /// is .
- /// -or-
- /// is .
- ///
- public bool Reject(Suggestion suggestion, DiscordMember staffMember)
- {
- if (suggestion is null)
- {
- throw new ArgumentNullException(nameof(suggestion));
- }
-
- if (staffMember is null)
- {
- throw new ArgumentNullException(nameof(staffMember));
- }
-
- if (!SetStatus(suggestion, SuggestionStatus.Rejected, staffMember))
- {
- return false;
- }
-
- _logger.LogInformation("{StaffMember} marked suggestion {Id} as REJECTED", staffMember, suggestion.Id);
-
- using SuggestionContext context = _contextFactory.CreateDbContext();
- context.Suggestions.Update(suggestion);
- context.SaveChanges();
- return true;
- }
-
///
/// Sets the message of a suggestion.
///
@@ -503,6 +435,9 @@ public bool SetStatus(Suggestion suggestion, SuggestionStatus status, DiscordMem
context.Suggestions.Update(suggestion);
context.SaveChanges();
+ _logger.LogInformation("{StaffMember} marked suggestion {Id} as {Status}", staffMember, suggestion.Id,
+ humanizedStatus);
+
_ = UpdateSuggestionAsync(suggestion);
return true;
}
diff --git a/USAGE.md b/USAGE.md
index 9f6527e..4af15da 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -38,21 +38,14 @@ Allow a user to send suggestions again.
## Implementing and Rejecting Suggestions
-### `/suggestion implement`
+### `/suggestion setstatus`
-Mark a suggestion as implemented.
+Change the status of a suggestion
-| Parameter | Required | Type | Description |
-|:-----------|:---------|:-------------------------|:-----------------------------|
-| suggestion | ✅ Yes | Suggestion or Message ID | The suggestion to implement. |
-
-### `/suggestion reject`
-
-Mark a suggestion as rejected.
-
-| Parameter | Required | Type | Description |
-|:-----------|:---------|:-------------------------|:--------------------------|
-| suggestion | ✅ Yes | Suggestion or Message ID | The suggestion to reject. |
+| Parameter | Required | Type | Description |
+|:-----------|:---------|:-------------------------|:---------------------------------------|
+| suggestion | ✅ Yes | Suggestion or Message ID | The suggestion whose status to change. |
+| status | ✅ Yes | SuggestionStatus | The new status of the suggestion. |
# Ephemeral responses