Skip to content

Commit 42404b0

Browse files
Automatically delete ban messages for compromised account bans
1 parent 50b1a0f commit 42404b0

File tree

7 files changed

+90
-24
lines changed

7 files changed

+90
-24
lines changed

Commands/Bans.cs

-5
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,6 @@ public async Task BankeepCmd(CommandContext ctx,
207207
return;
208208
}
209209
}
210-
reason = reason.Replace("`", "\\`").Replace("*", "\\*");
211-
if (banDuration == default)
212-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {targetMember.Mention} has been banned: **{reason}**");
213-
else
214-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {targetMember.Mention} has been banned for **{TimeHelpers.TimeToPrettyFormat(banDuration, false)}**: **{reason}**");
215210
}
216211

217212
[Command("unban")]

Commands/InteractionCommands/BanInteractions.cs

-5
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@ public async Task BanSlashCommand(InteractionContext ctx,
103103
return;
104104
}
105105
}
106-
reason = reason.Replace("`", "\\`").Replace("*", "\\*");
107-
if (banDuration == default)
108-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {user.Mention} has been banned: **{reason}**");
109-
else
110-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {user.Mention} has been banned for **{TimeHelpers.TimeToPrettyFormat(banDuration, false)}**: **{reason}**");
111106

112107
webhookOut.Content = $"{Program.cfgjson.Emoji.Success} User was successfully bonked.";
113108
await ctx.EditResponseAsync(webhookOut);

Helpers/BanHelpers.cs

+43-14
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@ public static async Task<bool> BanFromServerAsync(ulong targetUserId, string rea
1818
expireTime = null;
1919
}
2020

21-
MemberPunishment newBan = new()
21+
(DiscordMessage? dmMessage, DiscordMessage? chatMessage) output = new();
22+
23+
reason = reason.Replace("`", "\\`").Replace("*", "\\*");
24+
if (channel is not null)
2225
{
23-
MemberId = targetUserId,
24-
ModId = moderatorId,
25-
ServerId = guild.Id,
26-
ExpireTime = expireTime,
27-
ActionTime = actionTime,
28-
Reason = reason
29-
};
30-
31-
await Program.db.HashSetAsync("bans", targetUserId, JsonConvert.SerializeObject(newBan));
26+
if (banDuration == default)
27+
output.chatMessage = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} <@{targetUserId}> has been banned: **{reason}**");
28+
else
29+
output.chatMessage = await channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} <@{targetUserId}> has been banned for **{TimeHelpers.TimeToPrettyFormat(banDuration, false)}**: **{reason}**");
30+
}
3231

3332
try
3433
{
@@ -38,24 +37,54 @@ public static async Task<bool> BanFromServerAsync(ulong targetUserId, string rea
3837
if (appealable)
3938
{
4039
if (compromisedAccount)
41-
await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}**!\nReason: **{reason}**\nYou can appeal the ban here: <{Program.cfgjson.AppealLink}>\nBefore appealing, please follow these steps to protect your account:\n1. Reset your Discord account password. Even if you use MFA, this will reset all session tokens.\n2. Review active sessions and authorised app connections.\n3. Ensure your PC is free of malware.\n4. [Enable MFA](https://support.discord.com/hc/en-us/articles/219576828-Setting-up-Multi-Factor-Authentication) if not already.");
40+
output.dmMessage = await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}**!\nReason: **{reason}**\nYou can appeal the ban here: <{Program.cfgjson.AppealLink}>\nBefore appealing, please follow these steps to protect your account:\n1. Reset your Discord account password. Even if you use MFA, this will reset all session tokens.\n2. Review active sessions and authorised app connections.\n3. Ensure your PC is free of malware.\n4. [Enable MFA](https://support.discord.com/hc/en-us/articles/219576828-Setting-up-Multi-Factor-Authentication) if not already.");
4241
else
43-
await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}**!\nReason: **{reason}**\nYou can appeal the ban here: <{Program.cfgjson.AppealLink}>");
42+
output.dmMessage = await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}**!\nReason: **{reason}**\nYou can appeal the ban here: <{Program.cfgjson.AppealLink}>");
4443
}
4544
else
4645
{
47-
await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been permanently banned from **{guild.Name}**!\nReason: **{reason}**");
46+
output.dmMessage = await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been permanently banned from **{guild.Name}**!\nReason: **{reason}**");
4847
}
4948
}
5049
else
5150
{
52-
await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}** for {TimeHelpers.TimeToPrettyFormat(banDuration, false)}!\nReason: **{reason}**\nBan expires: <t:{TimeHelpers.ToUnixTimestamp(expireTime)}:R>");
51+
output.dmMessage = await targetMember.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} You have been banned from **{guild.Name}** for {TimeHelpers.TimeToPrettyFormat(banDuration, false)}!\nReason: **{reason}**\nBan expires: <t:{TimeHelpers.ToUnixTimestamp(expireTime)}:R>");
5352
}
5453
}
5554
catch
5655
{
5756
// A DM failing to send isn't important.
5857
}
58+
59+
MemberPunishment newBan = new()
60+
{
61+
MemberId = targetUserId,
62+
ModId = moderatorId,
63+
ServerId = guild.Id,
64+
ExpireTime = expireTime,
65+
ActionTime = actionTime,
66+
Reason = reason
67+
};
68+
69+
if (output.chatMessage is not null)
70+
newBan.ContextMessageReference = new()
71+
{
72+
MessageId = output.chatMessage.Id,
73+
ChannelId = output.chatMessage.ChannelId
74+
};
75+
76+
if (output.dmMessage is not null)
77+
newBan!.DmMessageReference = new()
78+
{
79+
MessageId = output.dmMessage.Id,
80+
ChannelId = output.dmMessage.ChannelId
81+
};
82+
83+
await Program.db.HashSetAsync("bans", targetUserId, JsonConvert.SerializeObject(newBan));
84+
85+
// If ban is for a compromised account, add to list so the context message can be more-easily deleted later
86+
if (compromisedAccount)
87+
Program.db.HashSet("compromisedAccountBans", targetUserId, JsonConvert.SerializeObject(newBan));
5988

6089
try
6190
{

Program.cs

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ static async Task Main(string[] _)
249249
Tasks.PunishmentTasks.CheckMutesAsync(),
250250
Tasks.PunishmentTasks.CheckBansAsync(),
251251
Tasks.PunishmentTasks.CheckAutomaticWarningsAsync(),
252+
Tasks.PunishmentTasks.CheckCompromisedAccountBansAsync(),
252253
Tasks.ReminderTasks.CheckRemindersAsync(),
253254
Tasks.RaidmodeTasks.CheckRaidmodeAsync(cfgjson.ServerID),
254255
Tasks.LockdownTasks.CheckUnlocksAsync(),

Structs.cs

+3
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ public class ConfigJson
286286

287287
[JsonProperty("autoWarnMsgAutoDeleteDays")]
288288
public int AutoWarnMsgAutoDeleteDays { get; private set; }
289+
290+
[JsonProperty("compromisedAccountBanMsgAutoDeleteDays")]
291+
public int CompromisedAccountBanMsgAutoDeleteDays { get; private set; }
289292

290293
[JsonProperty("logLevel")]
291294
public Level LogLevel { get; private set; } = Level.Information;

Tasks/PunishmentTasks.cs

+42
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,48 @@ public static async Task<bool> CheckAutomaticWarningsAsync()
9898
return success;
9999
}
100100
}
101+
102+
public static async Task<bool> CheckCompromisedAccountBansAsync()
103+
{
104+
if (Program.cfgjson.CompromisedAccountBanMsgAutoDeleteDays == 0)
105+
return false;
106+
107+
Dictionary<string, MemberPunishment> banList = Program.db.HashGetAll("compromisedAccountBans").ToDictionary(
108+
x => x.Name.ToString(),
109+
x => JsonConvert.DeserializeObject<MemberPunishment>(x.Value)
110+
);
111+
112+
if (banList.Keys.Count == 0)
113+
return false;
114+
else
115+
{
116+
// The success value will be changed later if any of the message deletes are successful.
117+
bool success = false;
118+
foreach (KeyValuePair<string, MemberPunishment> entry in banList)
119+
{
120+
MemberPunishment ban = entry.Value;
121+
122+
if (DateTime.Now > ban.ActionTime.Value.AddDays(Program.cfgjson.CompromisedAccountBanMsgAutoDeleteDays))
123+
{
124+
try
125+
{
126+
var contextMessage = await DiscordHelpers.GetMessageFromReferenceAsync(ban.ContextMessageReference);
127+
await contextMessage.DeleteAsync();
128+
Program.db.HashDelete("compromisedAccountBans", ban.MemberId);
129+
success = true;
130+
}
131+
catch (NullReferenceException)
132+
{
133+
// it's fine. trust me. we'll live.
134+
Program.db.HashDelete("compromisedAccountBans", ban.MemberId);
135+
continue;
136+
}
137+
}
138+
}
139+
Program.discord.Logger.LogDebug(Program.CliptokEventID, "Checked compromised account bans at {time} with result: {result}", DateTime.Now, success);
140+
return success;
141+
}
142+
}
101143
}
102144

103145
}

config.json

+1
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@
322322
"tqsMutedRole": 752821045408563230,
323323
"tqsMuteDurationHours": 2,
324324
"autoWarnMsgAutoDeleteDays": 3,
325+
"compromisedAccountBanMsgAutoDeleteDays": 3,
325326
"logLevel": "Debug",
326327
"lokiURL": "http://100.79.19.82:3100",
327328
"lokiServiceName": "cliptok",

0 commit comments

Comments
 (0)