5858class SearchNotFoundError (Exception ):
5959 pass
6060
61+
62+ def filter_messages (network , msg , target , messages , ignoreRegex , sedRegex ):
63+ """Applies all filters but the user-provided regexp, so it is safe to
64+ run in the main process."""
65+ for m in messages :
66+ if m .command in ('PRIVMSG' , 'NOTICE' ) and \
67+ ircutils .strEqual (m .args [0 ], msg .args [0 ]) and \
68+ m .tagged ('receivedBy' ) is not None and \
69+ m .tagged ('receivedBy' ).network == network :
70+ if target and m .nick != target :
71+ continue
72+ # Don't snarf ignored users' messages unless specifically
73+ # told to.
74+ if ircdb .checkIgnored (m .prefix ) and not target :
75+ continue
76+
77+ # Test messages sent before SedRegex was activated. Mark them all as seen
78+ # so we only need to do this check once per message.
79+ if not m .tagged (TAG_SEEN ):
80+ m .tag (TAG_SEEN )
81+ if sedRegex .match (m .args [1 ]):
82+ m .tag (TAG_IS_REGEX )
83+ # Ignore messages containing a regexp if ignoreRegex is on.
84+ if ignoreRegex and m .tagged (TAG_IS_REGEX ):
85+ continue
86+
87+ yield m
88+
89+ def get_first_matching_message (pattern , messages ):
90+ for m in messages :
91+ # When running substitutions, ignore the "* nick" part of any actions.
92+ action = ircmsgs .isAction (m )
93+ if action :
94+ text = ircmsgs .unAction (m )
95+ else :
96+ text = m .args [1 ]
97+
98+ replace_result = pattern .search (text )
99+ if replace_result :
100+ return m
101+
102+ def apply_substitution (pattern , replacement , m , count ):
103+ action = ircmsgs .isAction (m )
104+ if action :
105+ text = ircmsgs .unAction (m )
106+ else :
107+ text = m .args [1 ]
108+
109+ subst = pattern .sub (replacement , text , count )
110+ if action : # If the message was an ACTION, prepend the nick back.
111+ subst = '* %s %s' % (m .nick , subst )
112+
113+ return axe_spaces (subst )
114+
61115class SedRegex (callbacks .Plugin ):
62116 """
63117 Enable SedRegex on the desired channels:
@@ -175,6 +229,8 @@ def doPrivmsg(self, irc, msg):
175229 return
176230
177231 regex_timeout = self .registryValue ('processTimeout' )
232+ if self .registryValue ('boldReplacementText' , msg .channel , irc .network ):
233+ replacement = ircutils .bold (replacement )
178234 try :
179235 message = process (self ._replacer_process , irc , msg ,
180236 target , pattern , replacement , count , iterable , sedRegex ,
@@ -192,63 +248,35 @@ def doPrivmsg(self, irc, msg):
192248 else :
193249 irc .reply (message , prefixNick = False )
194250
195- def _replacer_process (self , irc , msg , target , pattern , replacement , count , messages , sedRegex ):
196- for m in messages :
197- if m .command in ('PRIVMSG' , 'NOTICE' ) and \
198- ircutils .strEqual (m .args [0 ], msg .args [0 ]) and m .tagged ('receivedBy' ) == irc :
199- if target and m .nick != target :
200- continue
201- # Don't snarf ignored users' messages unless specifically
202- # told to.
203- if ircdb .checkIgnored (m .prefix ) and not target :
204- continue
205-
206- # When running substitutions, ignore the "* nick" part of any actions.
207- action = ircmsgs .isAction (m )
208- if action :
209- text = ircmsgs .unAction (m )
210- else :
211- text = m .args [1 ]
212-
213- # Test messages sent before SedRegex was activated. Mark them all as seen
214- # so we only need to do this check once per message.
215- if not m .tagged (TAG_SEEN ):
216- m .tag (TAG_SEEN )
217- if sedRegex .match (m .args [1 ]):
218- m .tag (TAG_IS_REGEX )
219- # Ignore messages containing a regexp if ignoreRegex is on.
220- if self .registryValue ('ignoreRegex' , msg .channel , irc .network ) and m .tagged (TAG_IS_REGEX ):
221- self .log .debug ("Skipping message %s because it is tagged as isRegex" , m .args [1 ])
222- continue
223-
224- try :
225- replace_result = pattern .search (text )
226- if replace_result :
227- if self .registryValue ('boldReplacementText' ,
228- msg .channel , irc .network ):
229- replacement = ircutils .bold (replacement )
230- subst = pattern .sub (replacement , text , count )
231- if action : # If the message was an ACTION, prepend the nick back.
232- subst = '* %s %s' % (m .nick , subst )
233-
234- subst = axe_spaces (subst )
251+ def _format_result (self , irc , msg , m , subst ):
252+ if m .nick == msg .nick :
253+ fmt = self .registryValue ('format' , msg .channel , irc .network )
254+ env = {'replacement' : subst }
255+ else :
256+ fmt = self .registryValue ('format.other' , msg .channel , irc .network )
257+ env = {'otherNick' : msg .nick , 'replacement' : subst }
235258
236- if m .nick == msg .nick :
237- fmt = self .registryValue ('format' , msg .channel , irc .network )
238- env = {'replacement' : subst }
239- else :
240- fmt = self .registryValue ('format.other' , msg .channel , irc .network )
241- env = {'otherNick' : msg .nick , 'replacement' : subst }
259+ return ircutils .standardSubstitute (irc , m , fmt , env )
242260
243- return ircutils .standardSubstitute (irc , m , fmt , env )
261+ def _replacer_process (self , irc , msg , target , pattern , replacement , count ,
262+ messages , sedRegex ):
263+ ignoreRegex = self .registryValue ('ignoreRegex' , msg .channel , irc .network )
264+ messages = filter_messages (irc .network , msg , target , messages ,
265+ ignoreRegex , sedRegex )
244266
245- except Exception as e :
246- self .log .warning (_ ("SedRegex error: %s" ), e , exc_info = True )
247- raise
267+ try :
268+ m = get_first_matching_message (pattern , messages )
269+ if m :
270+ subst = apply_substitution (pattern , replacement , m , count )
271+ return self ._format_result (irc , msg , m , subst )
272+ except Exception as e :
273+ self .log .warning (_ ("SedRegex error: %s" ), e , exc_info = True )
274+ raise
248275
249276 self .log .debug (_ ("SedRegex: Search %r not found in the last %i messages of %s." ),
250277 msg .args [1 ], len (irc .state .history ), msg .args [0 ])
251278 raise SearchNotFoundError ()
279+
252280 doNotice = doPrivmsg
253281
254282Class = SedRegex
0 commit comments