Skip to content

Commit cbf936e

Browse files
committed
Add on_connect hooks and move nick/user/pass/cap ls command out of the core
1 parent e9a880a commit cbf936e

5 files changed

Lines changed: 89 additions & 13 deletions

File tree

cloudbot/clients/irc.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from _ssl import PROTOCOL_SSLv23
21
import asyncio
2+
import logging
33
import re
44
import ssl
5-
import logging
5+
from _ssl import PROTOCOL_SSLv23
66
from ssl import SSLContext
77

88
from cloudbot.client import Client
@@ -122,12 +122,11 @@ def connect(self):
122122
self._transport, self._protocol = yield from self.loop.create_connection(
123123
lambda: _IrcProtocol(self), host=self.server, port=self.port, ssl=self.ssl_context, **optional_params)
124124

125-
# send the cap ls, password, nick, and user
126-
self.send("CAP LS 302")
127-
self.set_pass(self.config["connection"].get("password"))
128-
self.set_nick(self.nick)
129-
self.cmd("USER", self.config.get('user', 'cloudbot'), "3", "*",
130-
self.config.get('realname', 'CloudBot - https://git.io/CloudBot'))
125+
tasks = [
126+
self.bot.plugin_manager.launch(hook, Event(bot=self.bot, conn=self, hook=hook))
127+
for hook in self.bot.plugin_manager.connect_hooks
128+
]
129+
yield from asyncio.gather(*tasks)
131130

132131
def quit(self, reason=None):
133132
if self._quit:

cloudbot/hook.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,21 @@ def _on_cap_ack_hook(func):
401401
return func
402402

403403
return _on_cap_ack_hook
404+
405+
406+
def on_connect(param=None, **kwargs):
407+
def _on_connect_hook(func):
408+
hook = _get_hook(func, "on_connect")
409+
if hook is None:
410+
hook = _Hook(func, "on_connect")
411+
_add_hook(func, hook)
412+
hook._add_hook(kwargs)
413+
return func
414+
415+
if callable(param):
416+
return _on_connect_hook(param)
417+
else:
418+
return lambda func: _on_connect_hook(func)
419+
420+
421+
connect = on_connect

cloudbot/plugin.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import re
88
from collections import defaultdict
9+
from operator import attrgetter
910

1011
import sqlalchemy
1112

@@ -19,7 +20,7 @@ def find_hooks(parent, module):
1920
"""
2021
:type parent: Plugin
2122
:type module: object
22-
:rtype: (list[CommandHook], list[RegexHook], list[RawHook], list[SieveHook], List[EventHook], List[PeriodicHook], list[OnStartHook], List[OnStopHook], list[OnCapAckHook], list[OnCapAvailableHook])
23+
:rtype: (list[CommandHook], list[RegexHook], list[RawHook], list[SieveHook], List[EventHook], List[PeriodicHook], list[OnStartHook], List[OnStopHook], list[OnCapAckHook], list[OnCapAvailableHook], list[OnConnectHook])
2324
"""
2425
# set the loaded flag
2526
module._cloudbot_loaded = True
@@ -33,9 +34,10 @@ def find_hooks(parent, module):
3334
on_stop = []
3435
on_cap_ack = []
3536
on_cap_available = []
37+
on_connect = []
3638
type_lists = {"command": command, "regex": regex, "irc_raw": raw, "sieve": sieve, "event": event,
3739
"periodic": periodic, "on_start": on_start, "on_stop": on_stop, "on_cap_ack": on_cap_ack,
38-
"on_cap_available": on_cap_available}
40+
"on_cap_available": on_cap_available, "on_connect": on_connect}
3941
for name, func in module.__dict__.items():
4042
if hasattr(func, "_cloudbot_hook"):
4143
# if it has cloudbot hook
@@ -47,7 +49,7 @@ def find_hooks(parent, module):
4749
# delete the hook to free memory
4850
del func._cloudbot_hook
4951

50-
return command, regex, raw, sieve, event, periodic, on_start, on_stop, on_cap_ack, on_cap_available
52+
return command, regex, raw, sieve, event, periodic, on_start, on_stop, on_cap_ack, on_cap_available, on_connect
5153

5254

5355
def find_tables(code):
@@ -103,6 +105,7 @@ def __init__(self, bot):
103105
self.regex_hooks = []
104106
self.sieves = []
105107
self.cap_hooks = {"on_available": defaultdict(list), "on_ack": defaultdict(list)}
108+
self.connect_hooks = []
106109
self._hook_waiting_queues = {}
107110

108111
@asyncio.coroutine
@@ -242,8 +245,14 @@ def load_plugin(self, path):
242245
self.sieves.append(sieve_hook)
243246
self._log_hook(sieve_hook)
244247

248+
# register connect hooks
249+
for connect_hook in plugin.connect_hooks:
250+
self.connect_hooks.append(connect_hook)
251+
self._log_hook(connect_hook)
252+
245253
# sort sieve hooks by priority
246254
self.sieves.sort(key=lambda x: x.priority)
255+
self.connect_hooks.sort(key=attrgetter("priority"))
247256

248257
# we don't need this anymore
249258
del plugin.run_on_start
@@ -325,6 +334,10 @@ def unload_plugin(self, path):
325334
for sieve_hook in plugin.sieves:
326335
self.sieves.remove(sieve_hook)
327336

337+
# unregister connect hooks
338+
for connect_hook in plugin.connect_hooks:
339+
self.connect_hooks.remove(connect_hook)
340+
328341
# Run on_stop hooks
329342
for on_stop_hook in plugin.run_on_stop:
330343
event = Event(bot=self.bot, hook=on_stop_hook)
@@ -552,8 +565,11 @@ def __init__(self, filepath, filename, title, code):
552565
self.file_path = filepath
553566
self.file_name = filename
554567
self.title = title
555-
self.commands, self.regexes, self.raw_hooks, self.sieves, self.events, self.periodic, self.run_on_start, self.run_on_stop, self.on_cap_ack, self.on_cap_available = find_hooks(
556-
self, code)
568+
hooks = find_hooks(self, code)
569+
self.commands, self.regexes, self.raw_hooks, *hooks = hooks
570+
self.sieves, self.events, self.periodic, *hooks = hooks
571+
self.run_on_start, self.run_on_stop, self.on_cap_ack, *hooks = hooks
572+
self.on_cap_available, self.connect_hooks, *hooks = hooks
557573
# we need to find tables for each plugin so that they can be unloaded from the global metadata when the
558574
# plugin is reloaded
559575
self.tables = find_tables(code)
@@ -830,6 +846,23 @@ def __init__(self, plugin, base_hook):
830846
super().__init__("ack", plugin, base_hook)
831847

832848

849+
class OnConnectHook(Hook):
850+
def __init__(self, plugin, sieve_hook):
851+
"""
852+
:type plugin: Plugin
853+
:type sieve_hook: cloudbot.util.hook._Hook
854+
"""
855+
856+
self.priority = sieve_hook.kwargs.pop("priority", 100)
857+
super().__init__("on_connect", plugin, sieve_hook)
858+
859+
def __repr__(self):
860+
return "{name}[{base!r}]".format(name=self.type, base=super())
861+
862+
def __str__(self):
863+
return "{name} {func} from {file}".format(name=self.type, func=self.function_name, file=self.plugin.file_name)
864+
865+
833866
_hook_name_to_plugin = {
834867
"command": CommandHook,
835868
"regex": RegexHook,
@@ -841,4 +874,5 @@ def __init__(self, plugin, base_hook):
841874
"on_stop": OnStopHook,
842875
"on_cap_available": OnCapAvaliableHook,
843876
"on_cap_ack": OnCapAckHook,
877+
"on_connect": OnConnectHook,
844878
}

plugins/cap.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
logger = logging.getLogger("cloudbot")
99

1010

11+
@asyncio.coroutine
12+
@hook.connect(priority=-10)
13+
def send_cap_ls(conn):
14+
conn.cmd("CAP", "LS", "302")
15+
16+
1117
@asyncio.coroutine
1218
def handle_available_caps(conn, caplist, event, irc_paramlist, bot):
1319
available_caps = conn.memory.setdefault("available_caps", set())

plugins/core_connect.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from cloudbot import hook
2+
3+
4+
@hook.connect(priority=0)
5+
def conn_pass(conn):
6+
conn.set_pass(conn.config["connection"].get("password"))
7+
8+
9+
@hook.connect(priority=10)
10+
def conn_nick(conn):
11+
conn.set_nick(conn.nick)
12+
13+
14+
@hook.connect(priority=20)
15+
def conn_user(conn):
16+
conn.cmd(
17+
"USER", conn.config.get('user', 'cloudbot'), "3", "*",
18+
conn.config.get('realname', 'CloudBot - https://git.io/CloudBot')
19+
)

0 commit comments

Comments
 (0)