def run(self): """ Connect to the IRC server and wait for messages to send. If connection is lost, automatically reconnect. """ while True: # Connect to IRC irc_sock = Irc(self.config) irc_sock.set_parser(IrcParser()) try: irc_sock.connect() except IrcError as e: logging.error('IRC error: {0}'.format(e.value)) time.sleep(1) continue # Send messages until disconnect while(True): out_msg = self.out_queue.get(block=True) out_str = 'PRIVMSG {0} : {1}\r\n'.format( self.config['irc']['channel'], out_msg) timeout = self.config['irc']['send_timeout'] sent_success = irc_sock.send_message(out_str, timeout=timeout) if not sent_success: logging.warning( 'IRC: failed to send chat message {0}'.format(out_str)) break GLib.idle_add(self.glib_func, ['DISCONNECTED'])
def run(self): """ Connect to the IRC server and send events to the GUI. This funtion is an endless loop that never exits, as it waits for a message before sending a signal to the GUI. If the connection to the server is lost, the connection is automatically re-established. In addition to the events defined by Irc, the following events are also sent: - CONNECTING: ['CONNECTING'] Connecting to the server. - CONNECTED: ['CONNECTED'] Connected to the server. - DISCONNECTED: ['DISCONNECTED'] Connection to the server lost. """ self.glib_func = self.func_queue.get() while True: # Connect to IRC GLib.idle_add(self.glib_func, ['CONNECTING']) irc_sock = Irc(self.config) irc_sock.set_parser(IrcParser()) try: irc_sock.connect('TWITCHCLIENT 1\r\n') except IrcError as e: logging.error('IRC error: {0}'.format(e.value)) time.sleep(1) continue GLib.idle_add(self.glib_func, ['CONNECTED']) # Receive messages until disconnect try: while(True): if irc_sock.receive_message(timeout=None): messages = irc_sock.parse_message() for msg in messages: GLib.idle_add(self.glib_func, msg) except IrcError: pass GLib.idle_add(self.glib_func, ['DISCONNECTED'])
class Client(object): """An IRC Client, designed to be pluggable""" def __init__(self, name, config): self.name = name self.config = config # Overall config self.options = config.clients[name] # Client options self.publisher = Publisher() # Initialize Irc connection object self.server = config.servers[self.options['server']] self.irc = Irc(self.server, self.publisher) # Configuration self.nick = self.options['nick'] self.stdio = StdIO() self.sending = Queue() self.receiving = Queue() # Plugins self.plugins = {} plugins = ['Base'] + self.options['plugins'].keys() [self.load_plugin(p) for p in plugins] self.instance = None def start(self): if self.instance is not None: raise self.publisher.subscribe(self.irc.sender, self.sending) self.publisher.subscribe(self.receiving, self.irc.receiver) # TODO: Remove, debugging self.publisher.subscribe(self.stdio.output, self.irc.receiver, str) self.publisher.subscribe(self.stdio.output, self.irc.sender, str) from lib.irc import Msg self.publisher.subscribe(self.sending, self.stdio.input, Msg.from_msg) self.irc.connect() self.instance = gevent.spawn(self._event_loop) return self.instance def kill(self): """Completely close connection to server""" while not self.sending.empty(): gevent.sleep(0.5) self.irc.kill() # TODO: Remove, debugging self.publisher.unsubscribe(self.irc.sender, self.sending) self.publisher.unsubscribe(self.receiving, self.irc.receiver) self.publisher.unsubscribe(self.stdio.output, self.irc.receiver) self.publisher.unsubscribe(self.stdio.output, self.irc.sender) self.stdio.stop() self.receiving.put(FinishLoop) def load_plugin(self, plugin): if self._load_module(plugin): if hasattr(self.plugins[plugin], 'setup'): settings = None if plugin in self.config.plugins: settings = self.config.plugins[plugin] botSettings = None if plugin in self.options['plugins']: botSettings = self.options['plugins'][plugin] self.plugins[plugin].setup(settings, botSettings) def _event_loop(self): gevent.spawn(self.plugins['Base'].on_connect) for msg in self.receiving: if msg is FinishLoop: break for plugin in self.plugins.values(): cmd = 'on_' + msg.cmd.lower() if hasattr(plugin, cmd): func = getattr(plugin, cmd) gevent.spawn(func, msg) if msg.ctcp is not None: cmd = 'on_ctcp_' + msg.ctcp[0].lower() if hasattr(plugin, cmd): func = getattr(plugin, cmd) gevent.spawn(func, msg) def _load_module(self, plugin): try: p_name = 'plugin.' + plugin.lower() p = __import__(p_name, fromlist=[plugin], level=-1) self.plugins[plugin] = getattr(p, plugin)(self) return True except ImportError as e: print str(e) return False