55import re
66import os
77import gc
8+ from operator import attrgetter
9+
810from sqlalchemy import create_engine
911
1012from sqlalchemy .orm import scoped_session , sessionmaker
1113from sqlalchemy .ext .declarative import declarative_base
1214from sqlalchemy .schema import MetaData
1315
14- import cloudbot
1516from cloudbot .client import Client
1617from cloudbot .config import Config
18+ from cloudbot .hook import Action
1719from cloudbot .reloader import PluginReloader
1820from cloudbot .plugin import PluginManager
1921from cloudbot .event import Event , CommandEvent , RegexEvent , EventType
@@ -221,23 +223,46 @@ def process(self, event):
221223 run_before_tasks = []
222224 tasks = []
223225 command_prefix = event .conn .config .get ('command_prefix' , '.' )
226+ halted = False
227+
228+ def add_hook (hook , _event , _run_before = False ):
229+ nonlocal halted
230+ if halted :
231+ return False
232+
233+ coro = self .plugin_manager .launch (hook , _event )
234+ if _run_before :
235+ run_before_tasks .append (coro )
236+ else :
237+ tasks .append (coro )
238+
239+ if hook .action is Action .HALTALL :
240+ halted = True
241+ return False
242+ elif hook .action is Action .HALTTYPE :
243+ return False
244+ return True
224245
225246 # Raw IRC hook
226247 for raw_hook in self .plugin_manager .catch_all_triggers :
227248 # run catch-all coroutine hooks before all others - TODO: Make this a plugin argument
228- if not raw_hook .threaded :
229- run_before_tasks . append (
230- self . plugin_manager . launch ( raw_hook , Event ( hook = raw_hook , base_event = event )))
231- else :
232- tasks . append ( self . plugin_manager . launch ( raw_hook , Event ( hook = raw_hook , base_event = event )))
249+ run_before = not raw_hook .threaded
250+ if not add_hook ( raw_hook , Event ( hook = raw_hook , base_event = event ), _run_before = run_before ):
251+ # The hook has an action of Action.HALT* so stop adding new tasks
252+ break
253+
233254 if event .irc_command in self .plugin_manager .raw_triggers :
234255 for raw_hook in self .plugin_manager .raw_triggers [event .irc_command ]:
235- tasks .append (self .plugin_manager .launch (raw_hook , Event (hook = raw_hook , base_event = event )))
256+ if not add_hook (raw_hook , Event (hook = raw_hook , base_event = event )):
257+ # The hook has an action of Action.HALT* so stop adding new tasks
258+ break
236259
237260 # Event hooks
238261 if event .type in self .plugin_manager .event_type_hooks :
239262 for event_hook in self .plugin_manager .event_type_hooks [event .type ]:
240- tasks .append (self .plugin_manager .launch (event_hook , Event (hook = event_hook , base_event = event )))
263+ if not add_hook (event_hook , Event (hook = event_hook , base_event = event )):
264+ # The hook has an action of Action.HALT* so stop adding new tasks
265+ break
241266
242267 if event .type is EventType .message :
243268 # Commands
@@ -258,7 +283,7 @@ def process(self, event):
258283 command_hook = self .plugin_manager .commands [command ]
259284 command_event = CommandEvent (hook = command_hook , text = text ,
260285 triggered_command = command , base_event = event )
261- tasks . append ( self . plugin_manager . launch ( command_hook , command_event ) )
286+ add_hook ( command_hook , command_event )
262287 else :
263288 potential_matches = []
264289 for potential_match , plugin in self .plugin_manager .commands .items ():
@@ -269,20 +294,27 @@ def process(self, event):
269294 command_hook = potential_matches [0 ][1 ]
270295 command_event = CommandEvent (hook = command_hook , text = text ,
271296 triggered_command = command , base_event = event )
272- tasks . append ( self . plugin_manager . launch ( command_hook , command_event ) )
297+ add_hook ( command_hook , command_event )
273298 else :
274299 event .notice ("Possible matches: {}" .format (
275300 formatting .get_text_list ([command for command , plugin in potential_matches ])))
276301
277302 # Regex hooks
303+ regex_matched = False
278304 for regex , regex_hook in self .plugin_manager .regex_hooks :
279305 if not regex_hook .run_on_cmd and cmd_match :
280- pass
281- else :
282- regex_match = regex .search (event .content )
283- if regex_match :
284- regex_event = RegexEvent (hook = regex_hook , match = regex_match , base_event = event )
285- tasks .append (self .plugin_manager .launch (regex_hook , regex_event ))
306+ continue
307+
308+ if regex_hook .only_no_match and regex_matched :
309+ continue
310+
311+ regex_match = regex .search (event .content )
312+ if regex_match :
313+ regex_matched = True
314+ regex_event = RegexEvent (hook = regex_hook , match = regex_match , base_event = event )
315+ if not add_hook (regex_hook , regex_event ):
316+ # The hook has an action of Action.HALT* so stop adding new tasks
317+ break
286318
287319 # Run the tasks
288320 yield from asyncio .gather (* run_before_tasks , loop = self .loop )
0 commit comments