66class 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