Skip to content

Commit 41f820f

Browse files
Merge branch 'main' into floatingmilkshake/dsp-command-migration
2 parents e8dc35c + 169be11 commit 41f820f

11 files changed

+137
-50
lines changed

Commands/BanCmds.cs

+16-13
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,18 @@ public async Task BanInfoSlashCommand(
157157
[HomeServer, RequireHomeserverPerm(ServerPermLevel.Moderator)]
158158
public async Task MassBanCmd(TextCommandContext ctx, [RemainingText] string input)
159159
{
160-
List<string> usersString = input.Replace("\n", " ").Replace("\r", "").Split(' ').ToList();
161-
List<ulong> users = usersString.Select(x => Convert.ToUInt64(x)).ToList();
160+
List<string> inputString = input.Replace("\n", " ").Replace("\r", "").Split(' ').ToList();
161+
List<ulong> users = new();
162+
string reason = "";
163+
foreach (var word in inputString)
164+
{
165+
if (ulong.TryParse(word, out var id))
166+
users.Add(id);
167+
else
168+
reason += $"{word} ";
169+
}
170+
reason = reason.Trim();
171+
162172
if (users.Count == 1 || users.Count == 0)
163173
{
164174
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Not accepting a massban with a single user. Please use `!ban`.");
@@ -173,7 +183,10 @@ public async Task MassBanCmd(TextCommandContext ctx, [RemainingText] string inpu
173183

174184
foreach (ulong user in users)
175185
{
176-
taskList.Add(BanSilently(ctx.Guild, user));
186+
if (string.IsNullOrWhiteSpace(reason))
187+
taskList.Add(BanSilently(ctx.Guild, user));
188+
else
189+
taskList.Add(BanSilently(ctx.Guild, user, $"Mass ban: {reason}"));
177190
}
178191

179192
var tasks = await Task.WhenAll(taskList);
@@ -272,11 +285,6 @@ public async Task BanCmd(TextCommandContext ctx,
272285
return;
273286
}
274287
}
275-
reason = reason.Replace("`", "\\`").Replace("*", "\\*");
276-
if (banDuration == default)
277-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {targetMember.Mention} has been banned: **{reason}**");
278-
else
279-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {targetMember.Mention} has been banned for **{TimeHelpers.TimeToPrettyFormat(banDuration, false)}**: **{reason}**");
280288
}
281289

282290
/// I CANNOT find a way to do this as alias so I made it a separate copy of the command.
@@ -357,11 +365,6 @@ public async Task BankeepCmd(TextCommandContext ctx,
357365
return;
358366
}
359367
}
360-
reason = reason.Replace("`", "\\`").Replace("*", "\\*");
361-
if (banDuration == default)
362-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {targetMember.Mention} has been banned: **{reason}**");
363-
else
364-
await ctx.Channel.SendMessageAsync($"{Program.cfgjson.Emoji.Banned} {targetMember.Mention} has been banned for **{TimeHelpers.TimeToPrettyFormat(banDuration, false)}**: **{reason}**");
365368
}
366369
}
367370
}

Commands/DebugCmds.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,14 @@ public async Task Refresh(TextCommandContext ctx)
133133
var msg = await ctx.GetResponseAsync();
134134
bool bans = await Tasks.PunishmentTasks.CheckBansAsync();
135135
bool mutes = await Tasks.PunishmentTasks.CheckMutesAsync();
136-
bool warns = await Tasks.PunishmentTasks.CheckAutomaticWarningsAsync();
136+
bool punishmentMessages = await Tasks.PunishmentTasks.CleanUpPunishmentMessagesAsync();
137137
bool reminders = await Tasks.ReminderTasks.CheckRemindersAsync();
138138
bool raidmode = await Tasks.RaidmodeTasks.CheckRaidmodeAsync(ctx.Guild.Id);
139139
bool unlocks = await Tasks.LockdownTasks.CheckUnlocksAsync();
140140
bool channelUpdateEvents = await Tasks.EventTasks.HandlePendingChannelUpdateEventsAsync();
141141
bool channelDeleteEvents = await Tasks.EventTasks.HandlePendingChannelDeleteEventsAsync();
142142

143-
await msg.ModifyAsync($"Unban check result: `{bans}`\nUnmute check result: `{mutes}`\nAutomatic warning message check result: `{warns}`\nReminders check result: `{reminders}`\nRaidmode check result: `{raidmode}`\nUnlocks check result: `{unlocks}`\nPending Channel Update events check result: `{channelUpdateEvents}`\nPending Channel Delete events check result: `{channelDeleteEvents}`");
143+
await msg.ModifyAsync($"Unban check result: `{bans}`\nUnmute check result: `{mutes}`\nPunishment message cleanup check result: `{punishmentMessages}`\nReminders check result: `{reminders}`\nRaidmode check result: `{raidmode}`\nUnlocks check result: `{unlocks}`\nPending Channel Update events check result: `{channelUpdateEvents}`\nPending Channel Delete events check result: `{channelDeleteEvents}`");
144144
}
145145

146146
[Command("sh")]

Commands/KickCmds.cs

+13-3
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,18 @@ public class KickCmds
5757
public async Task MassKickCmd(TextCommandContext ctx, [RemainingText] string input)
5858
{
5959

60-
List<string> usersString = input.Replace("\n", " ").Replace("\r", "").Split(' ').ToList();
61-
List<ulong> users = usersString.Select(x => Convert.ToUInt64(x)).ToList();
60+
List<string> inputString = input.Replace("\n", " ").Replace("\r", "").Split(' ').ToList();
61+
List<ulong> users = new();
62+
string reason = "";
63+
foreach (var word in inputString)
64+
{
65+
if (ulong.TryParse(word, out var id))
66+
users.Add(id);
67+
else
68+
reason += $"{word} ";
69+
}
70+
reason = reason.Trim();
71+
6272
if (users.Count == 1 || users.Count == 0)
6373
{
6474
await ctx.RespondAsync($"{Program.cfgjson.Emoji.Error} Not accepting a masskick with a single user. Please use `!ban`.");
@@ -79,7 +89,7 @@ public async Task MassKickCmd(TextCommandContext ctx, [RemainingText] string inp
7989
if (member is not null)
8090
{
8191

82-
taskList.Add(SafeKickAndLogAsync(member, "Mass kick", ctx.Member));
92+
taskList.Add(SafeKickAndLogAsync(member, $"Mass kick{(string.IsNullOrWhiteSpace(reason) ? "" : $": {reason}")}", ctx.Member));
8393
}
8494
}
8595
catch

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ RUN dotnet restore
88

99
# Copy source code and build
1010
COPY . ./
11-
RUN dotnet build -c Release -o out
11+
RUN dotnet publish Cliptok.csproj -c Release --property:PublishDir=$PWD/out
1212

1313
# We already have this image pulled, its actually quicker to reuse it
1414
FROM mcr.microsoft.com/dotnet/sdk:9.0.100 AS git-collector

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
{

Helpers/WarningHelpers.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ public static async Task<DiscordMessage> SendPublicWarningMessageAndDeleteInfrin
406406
// Return the sent warning message for logging.
407407

408408
var targetChannel = infringingMessage.Channel;
409-
if (infringingMessage.Channel.Type == DiscordChannelType.GuildForum)
409+
if (infringingMessage.Channel.Type == DiscordChannelType.GuildForum || infringingMessage.Channel.Parent.Type == DiscordChannelType.GuildForum)
410410
{
411411
if (Program.cfgjson.ForumChannelAutoWarnFallbackChannel == 0)
412412
Program.discord.Logger.LogWarning("A warning in forum channel {channelId} was attempted, but may fail due to the fallback channel not being set. Please set 'forumChannelAutoWarnFallbackChannel' in config.json to avoid this.", targetChannel.Id);

Lists/scams.txt

+3
Original file line numberDiff line numberDiff line change
@@ -544,3 +544,6 @@ serious about earning over $50K weekly in the digital market
544544
% of your profits once you start seeing earnings
545545
get started by asking (How)
546546
coach_davidrobert
547+
qCIKIQ
548+
5,000+ OnlyFans Models
549+
Teen, SnapChat & Other Packs

Program.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ static async Task Main(string[] _)
254254
[
255255
Tasks.PunishmentTasks.CheckMutesAsync(),
256256
Tasks.PunishmentTasks.CheckBansAsync(),
257-
Tasks.PunishmentTasks.CheckAutomaticWarningsAsync(),
257+
Tasks.PunishmentTasks.CleanUpPunishmentMessagesAsync(),
258258
Tasks.ReminderTasks.CheckRemindersAsync(),
259259
Tasks.RaidmodeTasks.CheckRaidmodeAsync(cfgjson.ServerID),
260260
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

+53-15
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,30 @@ public static async Task<bool> CheckMutesAsync()
5858
}
5959
}
6060

61-
public static async Task<bool> CheckAutomaticWarningsAsync()
61+
// Cleans up public messages for automatic warnings & bans for compromised accounts
62+
public static async Task<bool> CleanUpPunishmentMessagesAsync()
6263
{
63-
if (Program.cfgjson.AutoWarnMsgAutoDeleteDays == 0)
64+
if (Program.cfgjson.AutoWarnMsgAutoDeleteDays == 0 && Program.cfgjson.CompromisedAccountBanMsgAutoDeleteDays == 0)
6465
return false;
65-
66-
Dictionary<string, UserWarning> warnList = Program.db.HashGetAll("automaticWarnings").ToDictionary(
67-
x => x.Name.ToString(),
68-
x => JsonConvert.DeserializeObject<UserWarning>(x.Value)
69-
);
70-
71-
if (warnList is null | warnList.Keys.Count == 0)
72-
return false;
73-
else
66+
67+
// The success value will be changed later if any of the message deletes are successful.
68+
bool success = false;
69+
70+
if (Program.cfgjson.AutoWarnMsgAutoDeleteDays > 0)
7471
{
75-
// The success value will be changed later if any of the message deletes are successful.
76-
bool success = false;
72+
Dictionary<string, UserWarning> warnList = Program.db.HashGetAll("automaticWarnings").ToDictionary(
73+
x => x.Name.ToString(),
74+
x => JsonConvert.DeserializeObject<UserWarning>(x.Value)
75+
);
76+
7777
foreach (KeyValuePair<string, UserWarning> entry in warnList)
7878
{
7979
UserWarning warn = entry.Value;
80+
#if DEBUG
81+
if (DateTime.Now > warn.WarnTimestamp.AddSeconds(Program.cfgjson.AutoWarnMsgAutoDeleteDays))
82+
#else
8083
if (DateTime.Now > warn.WarnTimestamp.AddDays(Program.cfgjson.AutoWarnMsgAutoDeleteDays))
84+
#endif
8185
{
8286
try
8387
{
@@ -94,9 +98,43 @@ public static async Task<bool> CheckAutomaticWarningsAsync()
9498
}
9599
}
96100
}
97-
Program.discord.Logger.LogDebug(Program.CliptokEventID, "Checked automatic warnings at {time} with result: {result}", DateTime.Now, success);
98-
return success;
99101
}
102+
103+
if (Program.cfgjson.CompromisedAccountBanMsgAutoDeleteDays > 0)
104+
{
105+
Dictionary<string, MemberPunishment> banList = Program.db.HashGetAll("compromisedAccountBans").ToDictionary(
106+
x => x.Name.ToString(),
107+
x => JsonConvert.DeserializeObject<MemberPunishment>(x.Value)
108+
);
109+
110+
foreach (KeyValuePair<string, MemberPunishment> entry in banList)
111+
{
112+
MemberPunishment ban = entry.Value;
113+
#if DEBUG
114+
if (DateTime.Now > ban.ActionTime.Value.AddSeconds(Program.cfgjson.CompromisedAccountBanMsgAutoDeleteDays))
115+
#else
116+
if (DateTime.Now > ban.ActionTime.Value.AddDays(Program.cfgjson.CompromisedAccountBanMsgAutoDeleteDays))
117+
#endif
118+
{
119+
try
120+
{
121+
var contextMessage = await DiscordHelpers.GetMessageFromReferenceAsync(ban.ContextMessageReference);
122+
await contextMessage.DeleteAsync();
123+
Program.db.HashDelete("compromisedAccountBans", ban.MemberId);
124+
success = true;
125+
}
126+
catch (NullReferenceException)
127+
{
128+
// it's fine. trust me. we'll live.
129+
Program.db.HashDelete("compromisedAccountBans", ban.MemberId);
130+
continue;
131+
}
132+
}
133+
}
134+
}
135+
136+
Program.discord.Logger.LogDebug(Program.CliptokEventID, "Checked for auto-warn and compromised account ban messages at {time} with result: {result}", DateTime.Now, success);
137+
return success;
100138
}
101139
}
102140

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)