Skip to content

Commit 9d47b1a

Browse files
authored
Merge branch 'gonzobot' into gonzobot+nick-re-checks
2 parents e1677da + 4542cd1 commit 9d47b1a

8 files changed

Lines changed: 65 additions & 43 deletions

File tree

cloudbot/bot.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from sqlalchemy.schema import MetaData
1414
from watchdog.observers import Observer
1515

16-
from cloudbot.client import Client
16+
from cloudbot.client import Client, CLIENTS
1717
from cloudbot.clients.irc import IrcClient, irc_clean
1818
from cloudbot.config import Config
1919
from cloudbot.event import Event, CommandEvent, RegexEvent, EventType
@@ -151,15 +151,9 @@ def create_connections(self):
151151
# strip all spaces and capitalization from the connection name
152152
name = clean_name(config['name'])
153153
nick = config['nick']
154-
server = config['connection']['server']
155-
port = config['connection'].get('port', 6667)
156-
local_bind = (config['connection'].get('bind_addr', False), config['connection'].get('bind_port', 0))
157-
if local_bind[0] is False:
158-
local_bind = False
159-
160-
self.connections[name] = IrcClient(self, name, nick, config=config, channels=config['channels'],
161-
server=server, port=port, use_ssl=config['connection'].get('ssl', False),
162-
local_bind=local_bind)
154+
_type = config.get("type", "irc")
155+
156+
self.connections[name] = CLIENTS[_type](self, name, nick, config=config, channels=config['channels'])
163157
logger.debug("[{}] Created connection.".format(name))
164158

165159
@asyncio.coroutine
@@ -246,6 +240,9 @@ def add_hook(hook, _event, _run_before=False):
246240
if halted:
247241
return False
248242

243+
if hook.clients and _event.conn.type not in hook.clients:
244+
return True
245+
249246
coro = self.plugin_manager.launch(hook, _event)
250247
if _run_before:
251248
run_before_tasks.append(coro)

cloudbot/client.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@
77

88
logger = logging.getLogger("cloudbot")
99

10+
CLIENTS = {}
11+
12+
13+
def client(_type):
14+
def _decorate(cls):
15+
CLIENTS[_type] = cls
16+
cls._type = _type
17+
return cls
18+
19+
return lambda cls: _decorate(cls)
20+
1021

1122
class Client:
1223
"""
@@ -22,6 +33,8 @@ class Client:
2233
:type permissions: PermissionManager
2334
"""
2435

36+
_type = None
37+
2538
def __init__(self, bot, name, nick, *, channels=None, config=None):
2639
"""
2740
:type bot: cloudbot.bot.CloudBot
@@ -155,3 +168,7 @@ def is_nick_valid(self, nick):
155168
@property
156169
def connected(self):
157170
raise NotImplementedError
171+
172+
@property
173+
def type(self):
174+
return self._type

cloudbot/clients/irc.py

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,13 @@
77
from functools import partial
88
from ssl import SSLContext
99

10-
from cloudbot.client import Client
10+
from cloudbot.client import Client, client
1111
from cloudbot.event import Event, EventType, IrcOutEvent
1212
from cloudbot.util import async_util
1313
from cloudbot.util.parsers.irc import Message
1414

1515
logger = logging.getLogger("cloudbot")
1616

17-
irc_prefix_re = re.compile(r":([^ ]*) ([^ ]*) (.*)")
18-
irc_noprefix_re = re.compile(r"([^ ]*) (.*)")
19-
irc_netmask_re = re.compile(r"([^!@]*)!([^@]*)@(.*)")
20-
irc_param_re = re.compile(r"(?:^|(?<= ))(:.*|[^ ]+)")
21-
2217
irc_nick_re = re.compile(r'[A-Za-z0-9^{\}\[\]\-`_|\\]+')
2318

2419
irc_bad_chars = ''.join([chr(x) for x in list(range(0, 1)) + list(range(4, 32)) + list(range(127, 160))])
@@ -50,6 +45,7 @@ def decode(bytestring):
5045
return bytestring.decode('utf-8', errors='ignore')
5146

5247

48+
@client("irc")
5349
class IrcClient(Client):
5450
"""
5551
An implementation of Client for IRC.
@@ -60,27 +56,26 @@ class IrcClient(Client):
6056
:type _ignore_cert_errors: bool
6157
"""
6258

63-
def __init__(self, bot, name, nick, *, channels=None, config=None,
64-
server, port=6667, use_ssl=False, ignore_cert_errors=True, timeout=300, local_bind=False):
59+
def __init__(self, bot, name, nick, *, channels=None, config=None):
6560
"""
6661
:type bot: cloudbot.bot.CloudBot
6762
:type name: str
6863
:type nick: str
6964
:type channels: list[str]
7065
:type config: dict[str, unknown]
71-
:type server: str
72-
:type port: int
73-
:type use_ssl: bool
74-
:type ignore_cert_errors: bool
75-
:type timeout: int
7666
"""
7767
super().__init__(bot, name, nick, channels=channels, config=config)
7868

79-
self.use_ssl = use_ssl
80-
self._ignore_cert_errors = ignore_cert_errors
81-
self._timeout = timeout
82-
self.server = server
83-
self.port = port
69+
self.use_ssl = config['connection'].get('ssl', False)
70+
self._ignore_cert_errors = config['connection']['ignore_cert']
71+
self._timeout = config['connection'].get('timeout', 300)
72+
self.server = config['connection']['server']
73+
self.port = config['connection'].get('port', 6667)
74+
75+
local_bind = (config['connection'].get('bind_addr', False), config['connection'].get('bind_port', 0))
76+
if local_bind[0] is False:
77+
local_bind = False
78+
8479
self.local_bind = local_bind
8580
# create SSL context
8681
if self.use_ssl:
@@ -109,16 +104,15 @@ def describe_server(self):
109104

110105
@asyncio.coroutine
111106
def try_connect(self):
112-
timeout = self.config["connection"].get("timeout", 30)
113107
while True:
114108
try:
115-
yield from self.connect(timeout)
109+
yield from self.connect(self._timeout)
116110
except (asyncio.TimeoutError, OSError):
117111
logger.exception("[%s] Error occurred while connecting", self.name)
118112
else:
119113
break
120114

121-
yield from asyncio.sleep(random.randrange(timeout))
115+
yield from asyncio.sleep(random.randrange(self._timeout))
122116

123117
@asyncio.coroutine
124118
def connect(self, timeout=None):
@@ -153,6 +147,7 @@ def connect(self, timeout=None):
153147
tasks = [
154148
self.bot.plugin_manager.launch(hook, Event(bot=self.bot, conn=self, hook=hook))
155149
for hook in self.bot.plugin_manager.connect_hooks
150+
if not hook.clients or self.type in hook.clients
156151
]
157152
# TODO stop connecting if a connect hook fails?
158153
yield from asyncio.gather(*tasks)
@@ -236,22 +231,23 @@ def cmd(self, command, *params):
236231
else:
237232
self.send(command)
238233

239-
def send(self, line):
234+
def send(self, line, log=True):
240235
"""
241236
Sends a raw IRC line
242237
:type line: str
238+
:type log: bool
243239
"""
244240
if not self._connected:
245241
raise ValueError("Client must be connected to irc server to use send")
246-
self.loop.call_soon_threadsafe(self._send, line)
242+
self.loop.call_soon_threadsafe(self._send, line, log)
247243

248-
def _send(self, line):
244+
def _send(self, line, log=True):
249245
"""
250246
Sends a raw IRC line unchecked. Doesn't do connected check, and is *not* threadsafe
251247
:type line: str
248+
:type log: bool
252249
"""
253-
logger.info("[{}] >> {}".format(self.name, line))
254-
async_util.wrap_future(self._protocol.send(line), loop=self.loop)
250+
async_util.wrap_future(self._protocol.send(line, log=log), loop=self.loop)
255251

256252
@property
257253
def connected(self):
@@ -318,7 +314,7 @@ def eof_received(self):
318314
return True
319315

320316
@asyncio.coroutine
321-
def send(self, line):
317+
def send(self, line, log=True):
322318
# make sure we are connected before sending
323319
if not self._connected:
324320
yield from self._connected_future
@@ -354,6 +350,9 @@ def send(self, line):
354350
# the line must be encoded before we send it, one of the sieves didn't encode it, fall back to the default
355351
line = line.encode("utf-8", "replace")
356352

353+
if log:
354+
logger.info("[{}|out] >> {!r}".format(self.conn.name, line))
355+
357356
self._transport.write(line)
358357

359358
def data_received(self, data):
@@ -378,7 +377,7 @@ def data_received(self, data):
378377
# Reply to pings immediately
379378

380379
if command == "PING":
381-
async_util.wrap_future(self.send("PONG " + command_params[-1]), loop=self.loop)
380+
self.conn.send("PONG " + command_params[-1], log=False)
382381

383382
# Parse the command and params
384383

cloudbot/plugin.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,13 @@ def __init__(self, _type, plugin, func_hook):
730730
self.action = func_hook.kwargs.pop("action", Action.CONTINUE)
731731
self.priority = func_hook.kwargs.pop("priority", Priority.NORMAL)
732732

733+
clients = func_hook.kwargs.pop("clients", [])
734+
735+
if isinstance(clients, str):
736+
clients = [clients]
737+
738+
self.clients = clients
739+
733740
if func_hook.kwargs:
734741
# we should have popped all the args, so warn if there are any left
735742
logger.warning("Ignoring extra args {} from {}".format(func_hook.kwargs, self.description))

config.default.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
"connections": [
33
{
44
"name": "esper",
5+
"type": "irc",
56
"connection": {
67
"server": "irc.esper.net",
78
"port": 6667,
89
"ssl": false,
910
"ignore_cert": true,
10-
"password": ""
11+
"password": "",
12+
"timeout": 300
1113
},
1214
"nick": "MyCloudBot",
1315
"user": "cloudbot",

plugins/chan_track.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ def on_away(conn, nick, irc_paramlist):
445445

446446
@hook.irc_raw('352')
447447
def on_who(conn, irc_paramlist):
448-
_, ident, host, server, nick, status, realname = irc_paramlist
448+
_, _, ident, host, server, nick, status, realname = irc_paramlist
449449
realname = realname.split(None, 1)[1]
450450
user = conn.memory["users"][nick]
451451
status = list(status)

plugins/core/cap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from cloudbot.util.parsers.irc import CapList
99

1010

11-
@hook.connect(priority=-10)
11+
@hook.connect(priority=-10, clients="irc")
1212
def send_cap_ls(conn):
1313
conn.cmd("CAP", "LS", "302")
1414
conn.memory.setdefault("available_caps", set()).clear()

plugins/core/core_connect.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from cloudbot import hook
22

33

4-
@hook.connect(priority=0)
4+
@hook.connect(priority=0, clients="irc")
55
def conn_pass(conn):
66
conn.set_pass(conn.config["connection"].get("password"))
77

@@ -11,7 +11,7 @@ def conn_nick(conn):
1111
conn.set_nick(conn.nick)
1212

1313

14-
@hook.connect(priority=20)
14+
@hook.connect(priority=20, clients="irc")
1515
def conn_user(conn):
1616
conn.cmd(
1717
"USER", conn.config.get('user', 'cloudbot'), "3", "*",

0 commit comments

Comments
 (0)