77from functools import partial
88from ssl import SSLContext
99
10- from cloudbot .client import Client
10+ from cloudbot .client import Client , client
1111from cloudbot .event import Event , EventType , IrcOutEvent
1212from cloudbot .util import async_util
1313from cloudbot .util .parsers .irc import Message
1414
1515logger = 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-
2217irc_nick_re = re .compile (r'[A-Za-z0-9^{\}\[\]\-`_|\\]+' )
2318
2419irc_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" )
5349class 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 )
@@ -177,7 +172,6 @@ def close(self):
177172
178173 def message (self , target , * messages ):
179174 for text in messages :
180- text = "" .join (text .splitlines ())
181175 self .cmd ("PRIVMSG" , target , text )
182176
183177 def admin_log (self , text , console = True ):
@@ -189,11 +183,9 @@ def admin_log(self, text, console=True):
189183 logger .info ("[%s|admin] %s" , self .name , text )
190184
191185 def action (self , target , text ):
192- text = "" .join (text .splitlines ())
193186 self .ctcp (target , "ACTION" , text )
194187
195188 def notice (self , target , text ):
196- text = "" .join (text .splitlines ())
197189 self .cmd ("NOTICE" , target , text )
198190
199191 def set_nick (self , nick ):
@@ -239,22 +231,23 @@ def cmd(self, command, *params):
239231 else :
240232 self .send (command )
241233
242- def send (self , line ):
234+ def send (self , line , log = True ):
243235 """
244236 Sends a raw IRC line
245237 :type line: str
238+ :type log: bool
246239 """
247240 if not self ._connected :
248241 raise ValueError ("Client must be connected to irc server to use send" )
249- self .loop .call_soon_threadsafe (self ._send , line )
242+ self .loop .call_soon_threadsafe (self ._send , line , log )
250243
251- def _send (self , line ):
244+ def _send (self , line , log = True ):
252245 """
253246 Sends a raw IRC line unchecked. Doesn't do connected check, and is *not* threadsafe
254247 :type line: str
248+ :type log: bool
255249 """
256- logger .info ("[{}] >> {}" .format (self .name , line ))
257- 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 )
258251
259252 @property
260253 def connected (self ):
@@ -321,7 +314,7 @@ def eof_received(self):
321314 return True
322315
323316 @asyncio .coroutine
324- def send (self , line ):
317+ def send (self , line , log = True ):
325318 # make sure we are connected before sending
326319 if not self ._connected :
327320 yield from self ._connected_future
@@ -357,6 +350,9 @@ def send(self, line):
357350 # the line must be encoded before we send it, one of the sieves didn't encode it, fall back to the default
358351 line = line .encode ("utf-8" , "replace" )
359352
353+ if log :
354+ logger .info ("[{}|out] >> {!r}" .format (self .conn .name , line ))
355+
360356 self ._transport .write (line )
361357
362358 def data_received (self , data ):
@@ -381,7 +377,7 @@ def data_received(self, data):
381377 # Reply to pings immediately
382378
383379 if command == "PING" :
384- async_util . wrap_future ( self .send ("PONG " + command_params [- 1 ]), loop = self . loop )
380+ self .conn . send ("PONG " + command_params [- 1 ], log = False )
385381
386382 # Parse the command and params
387383
0 commit comments