summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Yu <andrew@andrewyu.org>2022-08-12 02:06:41 +0800
committerAndrew Yu <andrew@andrewyu.org>2022-08-12 02:06:41 +0800
commitbdef092a15b48d368fd1b500a18104338af09d90 (patch)
tree18028f4cfaa72f0040acfe16a3127a64545d43b8
parent5d4355bf5423a5bf4afe64659e92243f852caab2 (diff)
downloadirc-mod-bot-bdef092a15b48d368fd1b500a18104338af09d90.tar.gz
irc-mod-bot-bdef092a15b48d368fd1b500a18104338af09d90.zip
Fix kickban: Now we have a ban_mask()
-rw-r--r--TODO1
-rw-r--r--bot.py50
2 files changed, 35 insertions, 16 deletions
diff --git a/TODO b/TODO
index 3f9352f..ae221c7 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
- Keep track of channel modes, keep track of QUIT.
- Summon the GNU.
- Reload configuration on-the-fly.
+- Case sensitivity
diff --git a/bot.py b/bot.py
index 442623a..57befde 100644
--- a/bot.py
+++ b/bot.py
@@ -97,7 +97,6 @@ class Message:
class ProtocolViolation(Exception):
pass
-
def match_hostmask(hostmask: bytes, pattern: bytes) -> bool:
regexp = b""
for i in list(pattern):
@@ -119,6 +118,22 @@ def match_hostmask(hostmask: bytes, pattern: bytes) -> bool:
regexp += b"$"
return bool(re.compile(regexp, re.I).match(hostmask))
+def ban_mask(s: socket.socket, channel: Channel, mask: bytes, protect: list[User] = []) -> Optional[list[User]]:
+ nicks_to_kick: list[bytes] = []
+ users_to_kick: list[User] = []
+ for potential_target in channel.users:
+ if not (potential_target.nick and potential_target.ident and potential_target.host): continue
+ if match_hostmask(potential_target.nick + b"!" + potential_target.ident + b"@" + potential_target.host, mask):
+ if potential_target in protect:
+ return None
+ nicks_to_kick.append(potential_target.nick)
+ users_to_kick.append(potential_target)
+
+ send(s, b"MODE", channel.name, b"+b", mask)
+ for nick_to_kick in nicks_to_kick:
+ send(s, b"KICK", channel.name, nick_to_kick)
+ return users_to_kick
+
def is_admin(user: User) -> Optional[bool]:
if not (user.nick and user.ident and user.host):
@@ -523,30 +538,33 @@ def handle_privmsg(
reply(
s,
msg,
- b"I am not a channel operator, so I kickban people.",
+ b"I am not a channel operator, so I can't kickban people.",
)
return
kickban_string = chat_command[1]
if b"@" in kickban_string:
- if b"!" not in kickban_string:
- kickban_string = b"*!" + kickban_string
- send(s, b"MODE", channel.name, b"+b", kickban_string)
- i: int = 0
- for potential_target in channel.users:
- if not (potential_target.nick and potential_target.ident and potential_target.host): continue
- if match_hostmask(potential_target.nick + b"!" + potential_target.ident + b"@" + potential_target.host, kickban_string):
- send(s, b"KICK", channel.name, potential_target.nick)
- i += 1
- reply(s, msg, b"Done kickbanning mask %s, kicked %d clients." % (kickban_string, i))
+ kickban_mask = kickban_string
+ if b"!" not in kickban_mask:
+ kickban_mask = b"*!" + kickban_mask
+ n = ban_mask(s, channel, kickban_mask, protect=[me, msg.source])
+ if n is None:
+ reply(s, msg, b"I refuse to kick you or myself, for the sake of being kind!")
+ else:
+ reply(s, msg, b"Banned mask %s and kicked %d clients." % (kickban_mask, len(n)))
+
return
else:
try:
kickban_target = users[kickban_string]
assert kickban_target.nick and kickban_target.ident and kickban_target.host
- send(s, b"MODE", channel.name, b"+b", b"*!%s@%s" % (kickban_target.ident if (not kickban_target.ident.startswith(b"~")) else b"*", kickban_target.host))
- send(s, b"KICK", channel.name, kickban_target.nick)
- return
+ kickban_mask = b"*!%s@%s" % (kickban_target.ident if (not kickban_target.ident.startswith(b"~")) else b"*", kickban_target.host)
+ n = ban_mask(s, channel, kickban_mask, protect=[me, msg.source])
+ if n is None:
+ reply(s, msg, b"I refuse to kick you or myself, for the sake of being kind!")
+ else:
+ reply(s, msg, b"Banned mask %s and kicked %d clients." % (kickban_mask, len(n)))
+ return
except KeyError:
reply(s, msg, b"You didn't provide a hostmask for me to kickban, so I assumed it's a nickname, but I don't know %s." % kickban_string)
return
@@ -619,7 +637,7 @@ def handle_privmsg(
reply(s, msg, b"That's me, right?")
return
elif whois_target_nick == msg.source.nick:
- reply(s, msg, b"You should know enough about yourself.")
+ reply(s, msg, b"You should know enough about yourself. But oh well...")
try:
whois_target = users[whois_target_nick]
except KeyError: