Skip to content

Commit 68e25a6

Browse files
committed
rewrite message_filter.py to handle both message rejection and pattern replace
1 parent f0007a7 commit 68e25a6

File tree

1 file changed

+68
-52
lines changed

1 file changed

+68
-52
lines changed

modules/message_filter.py

Lines changed: 68 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@
66
class Module(ModuleManager.BaseModule):
77
_name = "Filter"
88

9+
def _split(self, s):
10+
backslash = False
11+
forward_slash = []
12+
for i, c in enumerate(s):
13+
if not backslash:
14+
if c == "/":
15+
forward_slash.append(i)
16+
if c == "\\":
17+
backslash = True
18+
else:
19+
backslash = False
20+
if forward_slash and (not forward_slash[-1] == (len(s)-1)):
21+
forward_slash.append(len(s))
22+
23+
last = 0
24+
out = []
25+
for i in forward_slash:
26+
out.append(s[last:i])
27+
last = i+1
28+
return out
29+
930
def _get_filters(self, server, target):
1031
filters = server.get_setting("message-filters", [])
1132
filters.extend(target.get_setting("message-filters", []))
@@ -14,7 +35,9 @@ def _get_filters(self, server, target):
1435
@utils.hook("preprocess.send.privmsg")
1536
@utils.hook("preprocess.send.notice")
1637
def channel_message(self, event):
17-
message = utils.irc.strip_font(event["line"].args[1])
38+
message = event["line"].args[1]
39+
message_plain = utils.irc.strip_font(message)
40+
original_message = message
1841
target_name = event["line"].args[0]
1942

2043
# strip off any STATUSMSG chars
@@ -27,61 +50,54 @@ def channel_message(self, event):
2750

2851
filters = self._get_filters(event["server"], target)
2952
for filter in filters:
30-
if re.search(filter, message):
31-
self.log.info("Message matched filter, dropping: %s"
32-
% event["line"].format())
33-
event["line"].invalidate()
34-
break
35-
36-
def _filter(self, target, args):
37-
subcommand = args[0]
38-
arg = args[1] if len(args) > 1 else None
39-
40-
message_filters = target.get_setting("message-filters", [])
41-
if subcommand == "list":
42-
if not arg:
43-
return "%d filters in place" % len(message_filters)
44-
else:
45-
index = int(arg)
46-
return "Filter %d: %s" % (index, message_filters[index])
47-
elif subcommand == "add":
48-
if arg == None:
49-
raise TypeError()
50-
message_filters = set(message_filters)
51-
message_filters.add(arg)
52-
target.set_setting("message-filters", list(message_filters))
53-
return "Added filter"
54-
elif subcommand == "remove":
55-
if arg == None:
56-
raise TypeError()
57-
58-
index = int(arg)
59-
message_filters = list(message_filters)
60-
filter = message_filters.pop(index)
61-
target.set_setting("message-filters", message_filters)
62-
return "Removed filter: %s" % filter
63-
else:
64-
return None
53+
type, pattern, *args = self._split(filter)
54+
if type == "m":
55+
if re.search(pattern, message_plain):
56+
self.log.info("Message matched filter, dropping: %s"
57+
% event["line"].format())
58+
event["line"].invalidate()
59+
return
60+
elif type == "s":
61+
replace, *args = args
62+
message = re.sub(pattern, replace, message)
63+
if not message == message_plain:
64+
event["line"].args[1] = message
6565

6666
@utils.hook("received.command.cfilter", min_args=1)
67+
@utils.kwarg("help", "Add a message filter for the current channel")
68+
@utils.kwarg("permissions", "cfilter")
69+
@utils.spec("!'list ?<index>int")
70+
@utils.spec("!'add ?<m/pattern/>string|<s/pattern/replace/>string")
71+
@utils.spec("!'remove !<index>int")
6772
def cfilter(self, event):
68-
"""
69-
:help: Add a message filter for the current channel
70-
:usage: list
71-
:usage: add <regex>
72-
:usage: remove <index>
73-
:permission: cfilter
74-
"""
7573
# mark output as "assured" so it can bypass filtering
7674
event["stdout"].assure()
7775
event["stderr"].assure()
76+
target = event["target"]
77+
filters = target.get_setting("message-filters", [])
78+
79+
if event["spec"][0] == "list":
80+
if event["spec"][1]:
81+
if not len(filters) > event["spec"][1]:
82+
raise utils.EventError("Filter index %d doesn't exist"
83+
% event["spec"][1])
84+
event["stdout"].write("Message filter %d: %s"
85+
% (event["spec"][1], filters[event["spec"][1]]))
86+
else:
87+
s = ", ".join(
88+
f"({i}) {s}" for i, s in enumerate(filters))
89+
event["stdout"].write("Message filters: %s" % s)
90+
91+
elif event["spec"][0] == "add":
92+
filters.append(event["spec"][1])
93+
target.set_setting("message-filters", filters)
94+
event["stdout"].write("Added filter %d" % (len(filters)-1))
95+
96+
elif event["spec"][0] == "remove":
97+
if not filters:
98+
raise utils.EventError("No filters")
7899

79-
try:
80-
out = self._filter(event["target"], event["args_split"])
81-
event["stdout"].write(out)
82-
except TypeError as e:
83-
event["stderr"].write("Please provide an argument")
84-
except ValueError:
85-
event["stderr"].write("Indexes must be numbers")
86-
except IndexError:
87-
event["stderr"].write("Unknown index")
100+
removed = filters.pop(event["spec"][1])
101+
target.set_setting("message-filters", filters)
102+
event["stdout"].write("Removed filter %d: %s" %
103+
(event["spec"][1], removed))

0 commit comments

Comments
 (0)