diff --git a/CHANGELOG.md b/CHANGELOG.md
index 04c2e3a..7adaa8d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ 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.6.1] - 2023-07-24
+
+### Added
+
+- Added additional suggestion states.
+
## [1.6.0] - 2023-07-24
### Added
@@ -104,6 +110,7 @@ implemented, accepted, or rejected.
- Initial release.
+[1.6.1]: https://github.com/BrackeysBot/SuggestionBot/releases/tag/v1.6.1
[1.6.0]: https://github.com/BrackeysBot/SuggestionBot/releases/tag/v1.6.0
[1.5.1]: https://github.com/BrackeysBot/SuggestionBot/releases/tag/v1.5.1
[1.5.0]: https://github.com/BrackeysBot/SuggestionBot/releases/tag/v1.5.0
diff --git a/SuggestionBot/Configuration/GuildConfiguration.cs b/SuggestionBot/Configuration/GuildConfiguration.cs
index 296edb0..b878bfa 100644
--- a/SuggestionBot/Configuration/GuildConfiguration.cs
+++ b/SuggestionBot/Configuration/GuildConfiguration.cs
@@ -29,6 +29,12 @@ public sealed class GuildConfiguration
/// if a thread should be created; otherwise, .
public bool CreateThreadForSuggestion { get; set; } = true;
+ ///
+ /// Gets or sets the embed color for implemented suggestions.
+ ///
+ /// The embed color for implemented suggestions.
+ public int DuplicateColor { get; set; } = 0xA0A0A0;
+
///
/// Gets or sets the embed color for implemented suggestions.
///
@@ -41,6 +47,12 @@ public sealed class GuildConfiguration
/// The log channel ID.
public ulong LogChannel { get; set; }
+ ///
+ /// Gets or sets the embed color for rejected suggestions.
+ ///
+ /// The embed color for rejected suggestions.
+ public int PlannedColor { get; set; } = 0x6495ED;
+
///
/// Gets or sets the embed color for rejected suggestions.
///
diff --git a/SuggestionBot/Data/SuggestionStatus.cs b/SuggestionBot/Data/SuggestionStatus.cs
index 9500eee..4f0a450 100644
--- a/SuggestionBot/Data/SuggestionStatus.cs
+++ b/SuggestionBot/Data/SuggestionStatus.cs
@@ -9,5 +9,8 @@ public enum SuggestionStatus
Rejected,
Implemented,
Accepted,
- Removed
+ Removed,
+ Duplicate,
+ AlreadyImplemented,
+ AlreadyPlanned
}
diff --git a/SuggestionBot/Resources/PrivateMessages.Designer.cs b/SuggestionBot/Resources/PrivateMessages.Designer.cs
index 11a660a..84c1a6b 100644
--- a/SuggestionBot/Resources/PrivateMessages.Designer.cs
+++ b/SuggestionBot/Resources/PrivateMessages.Designer.cs
@@ -71,6 +71,28 @@ internal static string AcceptedDescription {
}
}
+ ///
+ /// Looks up a localized string similar to {user.Mention}, your suggestion in **{guild.Name}** has been closed by staff because the changes you suggested are already present in the server.
+ ///
+ ///If you have any further questions, please reach us by sending a DM to ModMail..
+ ///
+ internal static string AlreadyImplementedDescription {
+ get {
+ return ResourceManager.GetString("AlreadyImplementedDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to {user.Mention}, your suggestion in **{guild.Name}** has been closed by staff because it was determined to be a duplicate of an existing suggestion which supersedes it or was previously closed.
+ ///
+ ///If you have any further questions, please reach us by sending a DM to ModMail..
+ ///
+ internal static string DuplicateDescription {
+ get {
+ return ResourceManager.GetString("DuplicateDescription", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Hi {user.Mention}. Your suggestion in **{guild.Name}** has been implemented and is now live in the server!
///Thank you for your contribution and feedback, and we hope you enjoy the new changes.
@@ -83,6 +105,17 @@ internal static string ImplementedDescription {
}
}
+ ///
+ /// Looks up a localized string similar to {user.Mention}, your suggestion in **{guild.Name}** has been closed by staff because the changes you suggested have already been planned for the server.
+ ///
+ ///If you have any further questions, please reach us by sending a DM to ModMail..
+ ///
+ internal static string PlannedDescription {
+ get {
+ return ResourceManager.GetString("PlannedDescription", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Hi {user.Mention}. Unfortunately, your suggestion in **{guild.Name}** has been rejected by staff at this time.
///Keep in mind that while a suggestion may be popular, there is no guarantee that it will be accepted. Nevertheless, we thank you for your contribution and feedback.
diff --git a/SuggestionBot/Resources/PrivateMessages.resx b/SuggestionBot/Resources/PrivateMessages.resx
index 76456ea..00f09de 100644
--- a/SuggestionBot/Resources/PrivateMessages.resx
+++ b/SuggestionBot/Resources/PrivateMessages.resx
@@ -24,6 +24,24 @@
+
+ {user.Mention}, your suggestion in **{guild.Name}** has been closed by staff because the changes you suggested have already been planned for the server.
+
+If you have any further questions, please reach us by sending a DM to ModMail.
+
+
+
+ {user.Mention}, your suggestion in **{guild.Name}** has been closed by staff because the changes you suggested are already present in the server.
+
+If you have any further questions, please reach us by sending a DM to ModMail.
+
+
+
+ {user.Mention}, your suggestion in **{guild.Name}** has been closed by staff because it was determined to be a duplicate of an existing suggestion which supersedes it or was previously closed.
+
+If you have any further questions, please reach us by sending a DM to ModMail.
+
+
{user.Mention}, your suggestion in **{guild.Name}** has been removed by staff because it was inappropriate or violated our server rules.
Repeated abuse will result in you losing access to the channel.
diff --git a/SuggestionBot/Services/MailmanService.cs b/SuggestionBot/Services/MailmanService.cs
index d386d3f..52331f6 100644
--- a/SuggestionBot/Services/MailmanService.cs
+++ b/SuggestionBot/Services/MailmanService.cs
@@ -115,6 +115,24 @@ private bool TryBuildEmbed(Suggestion suggestion, DiscordEmbedBuilder embed, Dis
embed.WithDescription(PrivateMessages.ImplementedDescription.FormatSmart(new { user = author, guild }));
break;
+ case SuggestionStatus.Duplicate:
+ embed.WithColor(configuration.DuplicateColor);
+ embed.WithTitle("Suggestion Closed (Duplicate)");
+ embed.WithDescription(PrivateMessages.DuplicateDescription.FormatSmart(new { user = author, guild }));
+ break;
+
+ case SuggestionStatus.AlreadyImplemented:
+ embed.WithColor(configuration.ImplementedColor);
+ embed.WithTitle("Suggestion Closed (Already Implemented)");
+ embed.WithDescription(PrivateMessages.DuplicateDescription.FormatSmart(new { user = author, guild }));
+ break;
+
+ case SuggestionStatus.AlreadyPlanned:
+ embed.WithColor(configuration.PlannedColor);
+ embed.WithTitle("Suggestion Closed (Already Planned)");
+ embed.WithDescription(PrivateMessages.PlannedDescription.FormatSmart(new { user = author, guild }));
+ break;
+
default:
return false;
}
diff --git a/SuggestionBot/Services/SuggestionService.cs b/SuggestionBot/Services/SuggestionService.cs
index abe48c5..7c7964e 100644
--- a/SuggestionBot/Services/SuggestionService.cs
+++ b/SuggestionBot/Services/SuggestionService.cs
@@ -64,37 +64,8 @@ public DiscordEmbed CreatePrivateEmbed(Suggestion suggestion)
return new DiscordEmbedBuilder();
}
- if (!_configurationService.TryGetGuildConfiguration(guild, out GuildConfiguration? configuration))
- {
- configuration = new GuildConfiguration();
- }
-
- string emoji = suggestion.Status switch
- {
- SuggestionStatus.Suggested => "🗳️",
- SuggestionStatus.Rejected => "❌",
- SuggestionStatus.Implemented => "✅",
- SuggestionStatus.Accepted => "✅",
- _ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
- };
-
DiscordUser author = GetAuthor(suggestion);
- var embed = new DiscordEmbedBuilder();
- string authorName = author.GetUsernameWithDiscriminator();
- embed.WithAuthor($"Suggestion from {authorName}", iconUrl: author.GetAvatarUrl(ImageFormat.Png));
- embed.WithThumbnail(guild.GetIconUrl(ImageFormat.Png));
- embed.WithDescription(suggestion.Content);
- embed.WithFooter($"Suggestion {suggestion.Id}");
- embed.WithColor(suggestion.Status switch
- {
- SuggestionStatus.Suggested => configuration.SuggestedColor,
- SuggestionStatus.Rejected => configuration.RejectedColor,
- SuggestionStatus.Implemented => configuration.ImplementedColor,
- SuggestionStatus.Accepted => configuration.AcceptedColor,
- _ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
- });
-
- embed.AddField("Status", $"{emoji} **{suggestion.Status.Humanize(LetterCasing.AllCaps)}**", true);
+ DiscordEmbedBuilder embed = CreateDefaultEmbed(suggestion, guild);
embed.AddField("Author", author.Mention, true);
embed.AddField("Submitted", Formatter.Timestamp(suggestion.Timestamp), true);
embed.AddField("View Suggestion", GetSuggestionLink(suggestion), true);
@@ -138,39 +109,7 @@ public DiscordEmbed CreatePublicEmbed(Suggestion suggestion)
return new DiscordEmbedBuilder();
}
- if (!_configurationService.TryGetGuildConfiguration(guild, out GuildConfiguration? configuration))
- {
- configuration = new GuildConfiguration();
- }
-
- string emoji = suggestion.Status switch
- {
- SuggestionStatus.Suggested => "🗳️",
- SuggestionStatus.Rejected => "❌",
- SuggestionStatus.Implemented => "✅",
- SuggestionStatus.Accepted => "✅",
- _ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
- };
-
- DiscordUser author = GetAuthor(suggestion);
- var embed = new DiscordEmbedBuilder();
- string authorName = author.GetUsernameWithDiscriminator();
- embed.WithAuthor($"Suggestion from {authorName}", iconUrl: author.GetAvatarUrl(ImageFormat.Png));
- embed.WithThumbnail(guild.GetIconUrl(ImageFormat.Png));
- embed.WithDescription(suggestion.Content);
- embed.WithFooter($"Suggestion {suggestion.Id}");
- embed.WithTimestamp(suggestion.Timestamp);
- embed.WithColor(suggestion.Status switch
- {
- SuggestionStatus.Suggested => configuration.SuggestedColor,
- SuggestionStatus.Rejected => configuration.RejectedColor,
- SuggestionStatus.Implemented => configuration.ImplementedColor,
- SuggestionStatus.Accepted => configuration.AcceptedColor,
- _ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
- });
-
- embed.AddField("Status", $"{emoji} **{suggestion.Status.Humanize(LetterCasing.AllCaps)}**", true);
-
+ DiscordEmbedBuilder embed = CreateDefaultEmbed(suggestion, guild);
if (!string.IsNullOrWhiteSpace(suggestion.Remarks))
{
embed.AddField("Staff Remarks", suggestion.Remarks);
@@ -695,6 +634,48 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken)
return Task.CompletedTask;
}
+ private DiscordEmbedBuilder CreateDefaultEmbed(Suggestion suggestion, DiscordGuild guild)
+ {
+ if (!_configurationService.TryGetGuildConfiguration(guild, out GuildConfiguration? configuration))
+ {
+ configuration = new GuildConfiguration();
+ }
+
+ string emoji = suggestion.Status switch
+ {
+ SuggestionStatus.Suggested => "🗳️",
+ SuggestionStatus.Rejected => "❌",
+ SuggestionStatus.Implemented => "✅",
+ SuggestionStatus.Accepted => "✅",
+ SuggestionStatus.Duplicate => "🔁",
+ SuggestionStatus.AlreadyImplemented => "✅",
+ SuggestionStatus.AlreadyPlanned => "📅",
+ _ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
+ };
+
+ DiscordUser author = GetAuthor(suggestion);
+ var embed = new DiscordEmbedBuilder();
+ string authorName = author.GetUsernameWithDiscriminator();
+ embed.WithAuthor($"Suggestion from {authorName}", iconUrl: author.GetAvatarUrl(ImageFormat.Png));
+ embed.WithThumbnail(guild.GetIconUrl(ImageFormat.Png));
+ embed.WithDescription(suggestion.Content);
+ embed.WithFooter($"Suggestion {suggestion.Id}");
+ embed.WithTimestamp(suggestion.Timestamp);
+ embed.WithColor(suggestion.Status switch
+ {
+ SuggestionStatus.Suggested => configuration.SuggestedColor,
+ SuggestionStatus.Rejected => configuration.RejectedColor,
+ SuggestionStatus.Implemented or SuggestionStatus.AlreadyImplemented => configuration.ImplementedColor,
+ SuggestionStatus.Accepted => configuration.AcceptedColor,
+ SuggestionStatus.Duplicate => configuration.DuplicateColor,
+ SuggestionStatus.AlreadyPlanned => configuration.PlannedColor,
+ _ => throw new ArgumentOutOfRangeException(nameof(suggestion), suggestion.Status, null)
+ });
+
+ embed.AddField("Status", $"{emoji} **{suggestion.Status.Humanize(LetterCasing.AllCaps)}**", true);
+ return embed;
+ }
+
private Task OnGuildAvailable(DiscordClient sender, GuildCreateEventArgs args)
{
DiscordGuild guild = args.Guild;
diff --git a/SuggestionBot/SuggestionBot.csproj b/SuggestionBot/SuggestionBot.csproj
index 0e89249..f62cd57 100644
--- a/SuggestionBot/SuggestionBot.csproj
+++ b/SuggestionBot/SuggestionBot.csproj
@@ -6,7 +6,7 @@
enable
enable
Linux
- 1.6.0
+ 1.6.1