Skip to content

Commit 27739a3

Browse files
committed
add more commands
1 parent 2fde9ef commit 27739a3

4 files changed

Lines changed: 133 additions & 25 deletions

File tree

MedalBOT/BotContext.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public class BotContext
6565
public Dictionary<string, DateTime> ServiceResponseTimeouts { get; set; }
6666
= new();
6767

68+
// Current active service request ID (one at a time)
69+
public string CurrentServiceRequestId { get; set; }
70+
6871
private readonly object _voicedLock = new();
6972
private readonly object _muteLock = new();
7073
private const string MutedIdsFile = "muted_ids.txt";

MedalBOT/Commands/ChanServCommand.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ public class ChanServCommand : ICommand
1010
public (bool handled, string response) Process(BotContext ctx, string senderNick, string message, string fullLine)
1111
{
1212
// !blist is Discord-only, handled via ProcessDiscord
13-
// Only allow !addban, !delban, !tb from IRC
14-
if (!message.StartsWith("!addban") && !message.StartsWith("!delban") && !message.StartsWith("!tb"))
13+
// Only allow !addban, !delban, !tb, !nickban from IRC
14+
if (!message.StartsWith("!addban") && !message.StartsWith("!delban") &&
15+
!message.StartsWith("!tb") && !message.StartsWith("!nickban"))
1516
return (false, null);
1617

1718
if (!ctx.Admins.Contains(senderNick))
@@ -26,14 +27,18 @@ public class ChanServCommand : ICommand
2627
if (message.StartsWith("!tb"))
2728
return HandleTimedBan(ctx, senderNick, message);
2829

30+
if (message.StartsWith("!nickban"))
31+
return HandleNickBan(ctx, senderNick, message);
32+
2933
return (false, null);
3034
}
3135

3236
public (bool handled, string response) ProcessDiscord(BotContext ctx, string senderNick, string message)
3337
{
3438
// Discord can use !blist and other commands
3539
if (!message.StartsWith("!blist") && !message.StartsWith("!addban") &&
36-
!message.StartsWith("!delban") && !message.StartsWith("!tb"))
40+
!message.StartsWith("!delban") && !message.StartsWith("!tb") &&
41+
!message.StartsWith("!nickban"))
3742
return (false, null);
3843

3944
if (!ctx.Admins.Contains(senderNick))
@@ -51,15 +56,19 @@ public class ChanServCommand : ICommand
5156
if (message.StartsWith("!tb"))
5257
return HandleTimedBan(ctx, senderNick, message);
5358

59+
if (message.StartsWith("!nickban"))
60+
return HandleNickBan(ctx, senderNick, message);
61+
5462
return (false, null);
5563
}
5664

5765
private (bool, string) HandleBanList(BotContext ctx, string senderNick, bool isDiscord)
5866
{
5967
string commandId = $"blist_{DateTime.UtcNow.Ticks}_{senderNick}";
68+
ctx.CurrentServiceRequestId = commandId;
6069
ctx.TrackServiceRequest(commandId, senderNick, isDiscord);
6170
ctx.Writer?.WriteLine($"PRIVMSG ChanServ :bans {ctx.Channel}");
62-
ctx.Logger?.Log($"[CHANSERV] {senderNick} requested banlist for {ctx.Channel} (ID: {commandId}) - Discord: {isDiscord}");
71+
ctx.Logger?.Log($"[CHANSERV] {senderNick} requested banlist for {ctx.Channel} (ID: {commandId})");
6372
return (false, null);
6473
}
6574

@@ -104,9 +113,25 @@ public class ChanServCommand : ICommand
104113
ctx.Logger?.Log($"[CHANSERV] {senderNick} added timed ban for {target} ({duration}) in {ctx.Channel}");
105114
return (false, null);
106115
}
116+
117+
private (bool, string) HandleNickBan(BotContext ctx, string senderNick, string message)
118+
{
119+
var parts = message.Split(' ', StringSplitOptions.RemoveEmptyEntries);
120+
if (parts.Length < 2)
121+
return (true, "Usage: !nickban <nick> [reason]");
122+
123+
string nick = parts[1];
124+
string reason = parts.Length > 2 ? string.Join(" ", parts.Skip(2)) : "Please change your nickname";
125+
126+
string mask = $"*{nick}*!*@*";
127+
ctx.Writer?.WriteLine($"PRIVMSG ChanServ :addban {ctx.Channel} {mask} {reason}");
128+
ctx.Logger?.Log($"[CHANSERV] {senderNick} nick-banned {nick} in {ctx.Channel}");
129+
return (false, null);
130+
}
107131
}
108132
}
109133

110134

111135

112136

137+

MedalBOT/Commands/SpamServCommand.cs

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ public class SpamServCommand : ICommand
1010
public (bool handled, string response) Process(BotContext ctx, string senderNick, string message, string fullLine)
1111
{
1212
if (!message.StartsWith("!badwords") && !message.StartsWith("!addbadword") &&
13-
!message.StartsWith("!delbadword"))
13+
!message.StartsWith("!delbadword") && !message.StartsWith("!wordban") &&
14+
!message.StartsWith("!unwordban") && !message.StartsWith("!wordlist"))
1415
return (false, null);
1516

1617
if (!ctx.Admins.Contains(senderNick))
@@ -25,6 +26,46 @@ public class SpamServCommand : ICommand
2526
if (message.StartsWith("!delbadword"))
2627
return HandleDelBadWord(ctx, senderNick, message);
2728

29+
if (message.StartsWith("!wordban"))
30+
return HandleWordBan(ctx, senderNick, message);
31+
32+
if (message.StartsWith("!unwordban"))
33+
return HandleUnwordBan(ctx, senderNick, message);
34+
35+
if (message.StartsWith("!wordlist"))
36+
return HandleWordList(ctx, senderNick, false);
37+
38+
return (false, null);
39+
}
40+
41+
public (bool handled, string response) ProcessDiscord(BotContext ctx, string senderNick, string message)
42+
{
43+
if (!message.StartsWith("!badwords") && !message.StartsWith("!addbadword") &&
44+
!message.StartsWith("!delbadword") && !message.StartsWith("!wordban") &&
45+
!message.StartsWith("!unwordban") && !message.StartsWith("!wordlist"))
46+
return (false, null);
47+
48+
if (!ctx.Admins.Contains(senderNick))
49+
return (true, "You must be an admin to use SpamServ commands.");
50+
51+
if (message.StartsWith("!badwords"))
52+
return HandleBadWordsList(ctx, senderNick);
53+
54+
if (message.StartsWith("!addbadword"))
55+
return HandleAddBadWord(ctx, senderNick, message);
56+
57+
if (message.StartsWith("!delbadword"))
58+
return HandleDelBadWord(ctx, senderNick, message);
59+
60+
if (message.StartsWith("!wordban"))
61+
return HandleWordBan(ctx, senderNick, message);
62+
63+
if (message.StartsWith("!unwordban"))
64+
return HandleUnwordBan(ctx, senderNick, message);
65+
66+
if (message.StartsWith("!wordlist"))
67+
return HandleWordList(ctx, senderNick, true);
68+
2869
return (false, null);
2970
}
3071

@@ -35,6 +76,16 @@ public class SpamServCommand : ICommand
3576
return (false, null);
3677
}
3778

79+
private (bool, string) HandleWordList(BotContext ctx, string senderNick, bool isDiscord)
80+
{
81+
string commandId = $"wordlist_{DateTime.UtcNow.Ticks}_{senderNick}";
82+
ctx.CurrentServiceRequestId = commandId;
83+
ctx.TrackServiceRequest(commandId, senderNick, isDiscord);
84+
ctx.Writer?.WriteLine($"PRIVMSG SpamServ :listbadwords {ctx.Channel}");
85+
ctx.Logger?.Log($"[SPAMSERV] {senderNick} requested badwords list for {ctx.Channel} (ID: {commandId})");
86+
return (false, null);
87+
}
88+
3889
private (bool, string) HandleAddBadWord(BotContext ctx, string senderNick, string message)
3990
{
4091
var parts = message.Split(' ', StringSplitOptions.RemoveEmptyEntries);
@@ -61,6 +112,36 @@ public class SpamServCommand : ICommand
61112
ctx.Logger?.Log($"[SPAMSERV] {senderNick} removed bad word '{word}' from {ctx.Channel}");
62113
return (false, null);
63114
}
115+
116+
private (bool, string) HandleWordBan(BotContext ctx, string senderNick, string message)
117+
{
118+
var parts = message.Split(' ', StringSplitOptions.RemoveEmptyEntries);
119+
if (parts.Length < 2)
120+
return (true, "Usage: !wordban <word> [reason]");
121+
122+
string word = parts[1];
123+
string reason = parts.Length > 2 ? string.Join(" ", parts.Skip(2)) : "Spam";
124+
125+
string wildcardWord = $"*{word}*";
126+
ctx.Writer?.WriteLine($"PRIVMSG SpamServ :addbadword {ctx.Channel} {wildcardWord} {reason}");
127+
ctx.Logger?.Log($"[SPAMSERV] {senderNick} word-banned '{word}' in {ctx.Channel}");
128+
return (false, null);
129+
}
130+
131+
private (bool, string) HandleUnwordBan(BotContext ctx, string senderNick, string message)
132+
{
133+
var parts = message.Split(' ', StringSplitOptions.RemoveEmptyEntries);
134+
if (parts.Length < 2)
135+
return (true, "Usage: !unwordban <word>");
136+
137+
string word = parts[1];
138+
string wildcardWord = $"*{word}*";
139+
140+
ctx.Writer?.WriteLine($"PRIVMSG SpamServ :delbadword {ctx.Channel} {wildcardWord}");
141+
ctx.Logger?.Log($"[SPAMSERV] {senderNick} removed word ban for '{word}' in {ctx.Channel}");
142+
return (false, null);
143+
}
64144
}
65145
}
66146

147+

MedalBOT/Program.cs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -140,31 +140,29 @@ static async Task Main()
140140
ParseWhoResponse(ctx, line);
141141
}
142142

143-
// Capture ChanServ NOTICE replies (sent to bot nick for service requests)
144-
if (line.Contains("NOTICE") && line.Contains("ChanServ") && ctx.PendingServiceRequests.Count > 0)
143+
// Capture ChanServ/SpamServ NOTICE replies (sent to bot nick for service requests)
144+
if (line.Contains("NOTICE") && (line.Contains("ChanServ") || line.Contains("SpamServ")) && !string.IsNullOrWhiteSpace(ctx.CurrentServiceRequestId))
145145
{
146146
string noticeContent = MessageParser.GetMessage(line);
147147
if (!string.IsNullOrWhiteSpace(noticeContent))
148148
{
149-
var lastRequest = ctx.PendingServiceRequests.LastOrDefault();
150-
if (lastRequest.Key != null)
151-
{
152-
// Initialize buffer if needed
153-
if (!ctx.ServiceResponseBuffer.ContainsKey(lastRequest.Key))
154-
ctx.ServiceResponseBuffer[lastRequest.Key] = new System.Collections.Generic.List<string>();
155-
156-
// Add to buffer
157-
ctx.ServiceResponseBuffer[lastRequest.Key].Add(noticeContent);
158-
ctx.Logger?.Log($"[CHANSERV] Buffering response ({ctx.ServiceResponseBuffer[lastRequest.Key].Count} lines): {noticeContent}");
159-
160-
// Reset timeout - update last received time
161-
ctx.ServiceResponseTimeouts[lastRequest.Key] = DateTime.UtcNow;
162-
}
149+
string requestId = ctx.CurrentServiceRequestId;
150+
151+
// Initialize buffer if needed
152+
if (!ctx.ServiceResponseBuffer.ContainsKey(requestId))
153+
ctx.ServiceResponseBuffer[requestId] = new System.Collections.Generic.List<string>();
154+
155+
// Add to buffer
156+
ctx.ServiceResponseBuffer[requestId].Add(noticeContent);
157+
ctx.Logger?.Log($"[SERVICE] Buffering response ({ctx.ServiceResponseBuffer[requestId].Count} lines): {noticeContent}");
158+
159+
// Reset timeout - update last received time
160+
ctx.ServiceResponseTimeouts[requestId] = DateTime.UtcNow;
163161
}
164162
continue;
165163
}
166164

167-
// Check for timed-out ChanServ responses (2 second timeout)
165+
// Check for timed-out service responses (2 second timeout)
168166
const int timeoutMs = 2000;
169167
var expiredRequests = ctx.ServiceResponseTimeouts
170168
.Where(kvp => (DateTime.UtcNow - kvp.Value).TotalMilliseconds > timeoutMs)
@@ -180,14 +178,14 @@ static async Task Main()
180178
string requesterNick = requestInfo.RequesterNick;
181179
bool isDiscord = requestInfo.IsDiscord;
182180

183-
ctx.Logger?.Log($"[CHANSERV TIMEOUT] Response complete: {responses.Count} lines for {requesterNick}");
181+
ctx.Logger?.Log($"[SERVICE TIMEOUT] Response complete: {responses.Count} lines for {requesterNick}");
184182

185183
string fullResponse = string.Join("\n", responses);
186184

187185
if (isDiscord)
188186
{
189-
ctx.Logger?.Log($"[CHANSERV RELAY] Sending to Discord...");
190-
await ctx.Discord?.SendMessage($"**{requesterNick}** banlist:\n```\n{fullResponse}\n```");
187+
ctx.Logger?.Log($"[SERVICE RELAY] Sending to Discord...");
188+
await ctx.Discord?.SendMessage($"**{requesterNick}**:\n```\n{fullResponse}\n```");
191189
}
192190
else
193191
{
@@ -201,6 +199,7 @@ static async Task Main()
201199
ctx.PendingServiceRequests.Remove(requestId);
202200
ctx.ServiceResponseBuffer.Remove(requestId);
203201
ctx.ServiceResponseTimeouts.Remove(requestId);
202+
ctx.CurrentServiceRequestId = null;
204203
}
205204
}
206205

0 commit comments

Comments
 (0)