diff --git a/locale/Messages.resx b/locale/Messages.resx
index c2be4cd..dfaff85 100644
--- a/locale/Messages.resx
+++ b/locale/Messages.resx
@@ -585,6 +585,12 @@
Report an issue
+
+ See you soon, {0}!
+
+
+ Leave message
+
Time specified incorrectly!
diff --git a/locale/Messages.ru.resx b/locale/Messages.ru.resx
index d38509c..6169a13 100644
--- a/locale/Messages.ru.resx
+++ b/locale/Messages.ru.resx
@@ -585,6 +585,12 @@
Сообщить о проблеме
+
+ До скорой встречи, {0}!
+
+
+ Сообщение о выходе
+
Неправильно указано время!
diff --git a/locale/Messages.tt-ru.resx b/locale/Messages.tt-ru.resx
index dfb1ee6..3118e74 100644
--- a/locale/Messages.tt-ru.resx
+++ b/locale/Messages.tt-ru.resx
@@ -585,6 +585,12 @@
зарепортить баг
+
+ ну, мы потеряли {0}
+
+
+ до свидания (типо настройка)
+
ты там правильно напиши таймспан
diff --git a/src/Commands/BanCommandGroup.cs b/src/Commands/BanCommandGroup.cs
index c350729..30cff14 100644
--- a/src/Commands/BanCommandGroup.cs
+++ b/src/Commands/BanCommandGroup.cs
@@ -181,17 +181,19 @@ public class BanCommandGroup : CommandGroup
await _channelApi.CreateMessageWithEmbedResultAsync(dmChannel.ID, embedResult: dmEmbed, ct: ct);
}
+ var memberData = data.GetOrCreateMemberData(target.ID);
+ memberData.BannedUntil
+ = duration is not null ? DateTimeOffset.UtcNow.Add(duration.Value) : DateTimeOffset.MaxValue;
+
var banResult = await _guildApi.CreateGuildBanAsync(
guild.ID, target.ID, reason: $"({executor.GetTag()}) {reason}".EncodeHeader(),
ct: ct);
if (!banResult.IsSuccess)
{
+ memberData.BannedUntil = null;
return Result.FromError(banResult.Error);
}
- var memberData = data.GetOrCreateMemberData(target.ID);
- memberData.BannedUntil
- = duration is not null ? DateTimeOffset.UtcNow.Add(duration.Value) : DateTimeOffset.MaxValue;
memberData.Roles.Clear();
var embed = new EmbedBuilder().WithSmallTitle(
diff --git a/src/Commands/KickCommandGroup.cs b/src/Commands/KickCommandGroup.cs
index 0faa1d3..59c4045 100644
--- a/src/Commands/KickCommandGroup.cs
+++ b/src/Commands/KickCommandGroup.cs
@@ -143,17 +143,19 @@ public class KickCommandGroup : CommandGroup
await _channelApi.CreateMessageWithEmbedResultAsync(dmChannel.ID, embedResult: dmEmbed, ct: ct);
}
+ var memberData = data.GetOrCreateMemberData(target.ID);
+ memberData.Kicked = true;
+
var kickResult = await _guildApi.RemoveGuildMemberAsync(
guild.ID, target.ID, $"({executor.GetTag()}) {reason}".EncodeHeader(),
ct);
if (!kickResult.IsSuccess)
{
+ memberData.Kicked = false;
return Result.FromError(kickResult.Error);
}
- var memberData = data.GetOrCreateMemberData(target.ID);
memberData.Roles.Clear();
- memberData.Kicked = true;
var title = string.Format(Messages.UserKicked, target.GetTag());
var description = MarkdownExtensions.BulletPoint(string.Format(Messages.DescriptionActionReason, reason));
diff --git a/src/Commands/SettingsCommandGroup.cs b/src/Commands/SettingsCommandGroup.cs
index 86f031f..97ebc32 100644
--- a/src/Commands/SettingsCommandGroup.cs
+++ b/src/Commands/SettingsCommandGroup.cs
@@ -39,6 +39,7 @@ public class SettingsCommandGroup : CommandGroup
[
GuildSettings.Language,
GuildSettings.WelcomeMessage,
+ GuildSettings.LeaveMessage,
GuildSettings.ReceiveStartupMessages,
GuildSettings.RemoveRolesOnMute,
GuildSettings.ReturnRolesOnRejoin,
diff --git a/src/Data/GuildSettings.cs b/src/Data/GuildSettings.cs
index 5a99505..518465b 100644
--- a/src/Data/GuildSettings.cs
+++ b/src/Data/GuildSettings.cs
@@ -13,17 +13,29 @@ public static class GuildSettings
public static readonly LanguageOption Language = new("Language", "en");
///
- /// Controls what message should be sent in when a new member joins the server.
+ /// Controls what message should be sent in when a new member joins the guild.
///
///
///
/// - No message will be sent if set to "off", "disable" or "disabled".
- /// - will be sent if set to "default" or "reset"
+ /// - will be sent if set to "default" or "reset".
///
///
///
public static readonly Option WelcomeMessage = new("WelcomeMessage", "default");
+ ///
+ /// Controls what message should be sent in when a member leaves the guild.
+ ///
+ ///
+ ///
+ /// - No message will be sent if set to "off", "disable" or "disabled".
+ /// - will be sent if set to "default" or "reset".
+ ///
+ ///
+ ///
+ public static readonly Option LeaveMessage = new("LeaveMessage", "default");
+
///
/// Controls whether or not the message should be sent
/// in on startup.
diff --git a/src/Data/Options/AllOptionsEnum.cs b/src/Data/Options/AllOptionsEnum.cs
index e9637d6..6932822 100644
--- a/src/Data/Options/AllOptionsEnum.cs
+++ b/src/Data/Options/AllOptionsEnum.cs
@@ -14,6 +14,7 @@ public enum AllOptionsEnum
{
[UsedImplicitly] Language,
[UsedImplicitly] WelcomeMessage,
+ [UsedImplicitly] LeaveMessage,
[UsedImplicitly] ReceiveStartupMessages,
[UsedImplicitly] RemoveRolesOnMute,
[UsedImplicitly] ReturnRolesOnRejoin,
diff --git a/src/Messages.Designer.cs b/src/Messages.Designer.cs
index 707c814..0fa4820 100644
--- a/src/Messages.Designer.cs
+++ b/src/Messages.Designer.cs
@@ -1037,18 +1037,26 @@ namespace Octobot {
}
}
- internal static string InvalidTimeSpan
- {
- get
- {
+ internal static string DefaultLeaveMessage {
+ get {
+ return ResourceManager.GetString("DefaultLeaveMessage", resourceCulture);
+ }
+ }
+
+ internal static string SettingsLeaveMessage {
+ get {
+ return ResourceManager.GetString("SettingsLeaveMessage", resourceCulture);
+ }
+ }
+
+ internal static string InvalidTimeSpan {
+ get {
return ResourceManager.GetString("InvalidTimeSpan", resourceCulture);
}
}
- internal static string UserInfoKicked
- {
- get
- {
+ internal static string UserInfoKicked {
+ get {
return ResourceManager.GetString("UserInfoKicked", resourceCulture);
}
}
diff --git a/src/Responders/GuildMemberLeftResponder.cs b/src/Responders/GuildMemberLeftResponder.cs
new file mode 100644
index 0000000..5c6db36
--- /dev/null
+++ b/src/Responders/GuildMemberLeftResponder.cs
@@ -0,0 +1,73 @@
+using JetBrains.Annotations;
+using Octobot.Data;
+using Octobot.Extensions;
+using Octobot.Services;
+using Remora.Discord.API.Abstractions.Gateway.Events;
+using Remora.Discord.API.Abstractions.Rest;
+using Remora.Discord.Extensions.Embeds;
+using Remora.Discord.Gateway.Responders;
+using Remora.Results;
+
+namespace Octobot.Responders;
+
+///
+/// Handles sending a guild's if one is set.
+///
+///
+[UsedImplicitly]
+public class GuildMemberLeftResponder : IResponder
+{
+ private readonly IDiscordRestChannelAPI _channelApi;
+ private readonly IDiscordRestGuildAPI _guildApi;
+ private readonly GuildDataService _guildData;
+
+ public GuildMemberLeftResponder(
+ IDiscordRestChannelAPI channelApi, GuildDataService guildData, IDiscordRestGuildAPI guildApi)
+ {
+ _channelApi = channelApi;
+ _guildData = guildData;
+ _guildApi = guildApi;
+ }
+
+ public async Task RespondAsync(IGuildMemberRemove gatewayEvent, CancellationToken ct = default)
+ {
+ var user = gatewayEvent.User;
+ var data = await _guildData.GetData(gatewayEvent.GuildID, ct);
+ var cfg = data.Settings;
+
+ var memberData = data.GetOrCreateMemberData(user.ID);
+ if (memberData.BannedUntil is not null || memberData.Kicked)
+ {
+ return Result.FromSuccess();
+ }
+
+ if (GuildSettings.WelcomeMessagesChannel.Get(cfg).Empty()
+ || GuildSettings.LeaveMessage.Get(cfg) is "off" or "disable" or "disabled")
+ {
+ return Result.FromSuccess();
+ }
+
+ Messages.Culture = GuildSettings.Language.Get(cfg);
+ var leaveMessage = GuildSettings.LeaveMessage.Get(cfg) is "default" or "reset"
+ ? Messages.DefaultLeaveMessage
+ : GuildSettings.LeaveMessage.Get(cfg);
+
+ var guildResult = await _guildApi.GetGuildAsync(gatewayEvent.GuildID, ct: ct);
+ if (!guildResult.IsDefined(out var guild))
+ {
+ return Result.FromError(guildResult);
+ }
+
+ var embed = new EmbedBuilder()
+ .WithSmallTitle(string.Format(leaveMessage, user.GetTag(), guild.Name), user)
+ .WithGuildFooter(guild)
+ .WithTimestamp(DateTimeOffset.UtcNow)
+ .WithColour(ColorsList.Black)
+ .Build();
+
+ return await _channelApi.CreateMessageWithEmbedResultAsync(
+ GuildSettings.WelcomeMessagesChannel.Get(cfg), embedResult: embed,
+ allowedMentions: Octobot.NoMentions, ct: ct);
+ }
+}
+