def connect(self): # Try to connect if self.connected: buffer.put('>>We are already connected') try: self.socket = IrcSocket() self.socket.connect(self.host, self.port) self.socket.put_raw(f"USER {self.user} 0 * :{self.real}") # TODO Support alternate nick self.socket.put_raw(f"NICK {self.nick}") self.stop_thread = False # used to stop the thread when connection dies self.receive_thread = threading.Thread(target=self.get_messages, args=(self.stop_thread, self.buffer,), daemon=True) self.receive_thread.start() self.connected = True except OSError as err: logging.error(err) self.buffer.put(f'>>Connection failed due to error: {err}') self.disconnect()
def __init__(self): """ Initialize variables and read config. """ sys.path.append("plugins") self.loaded_plugins = {} # plugin name : module self.cmd_callbacks = {} # command : set(function) self.privmsg_cmd_callbacks = {} # command : set(function) self.command_masks = {} # command : list(regexp) self.plugins = set(config.LOAD_PLUGINS) self.cmd_prefixes = set(config.CMD_PREFIXES) self.nick = config.NICK self.username = config.USERNAME self.realname = config.REALNAME self.server, self.port = config.SERVER self.channels = config.CHANNELS self.socket = IrcSocket(self.server, self.port, self.nick, self.username, self.realname) self.socket.register_readline_cb(self.parse_line) for channel in self.channels: self.socket.join(channel) for plugin in self.plugins: print self.load_plugin(plugin)[1]
def main(): """ Main method to get started opens connection and starts endless while loop for polling IRC Channel """ args = parse() # set our settings for this run settings["app_dir"] = os.getcwd() settings["paperman"] = settings[platform.system()] settings["game"] = args.game if args.game else helpers.config_get("game") settings["ironman"] = args.ironman if args.ironman else helpers.config_get( "ironman") settings[ "language"] = args.language if args.language else helpers.config_get( "language") # language option commands = { 'truces': '!truces', 'ideas': '!ideas', 'ae': '!ae', 'mods': '!mods' } if settings["language"] == 'german': commands['truces'] = '!waffenstillstand' commands['ideas'] = '!ideen' # do some logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) logging.info(commands) # open connection connection = IrcSocket(args) # this'll run as long as you don't kill it while 1: text = connection.sock.recv(2040).decode() logger.info(text) # answer pings to stay connected if 'PING' in text: logger.info('Answer ping') connection.send_ping('PONG :tmi.twitch.tv\r\n') # ignore messages that aren't commands # only catches commmands if at the beginning of the message elif ':!' not in text: pass else: try: user = text[text.index('!') + 1:text.index('@')] except ValueError: continue #some default twitch messages don't fit the bill, but don't give us a user anyway text = text[text.rfind(':') + 1:].strip() # get ideas if text.startswith(commands.get('ideas')): connection.send_msg(user.title() + ': ' + getinfo.get_ideas()) #get mods from settings elif text.startswith(commands.get('mods')): connection.send_msg(user.title() + ': ' + getinfo.get_mods()) #get ae elif text.startswith(commands.get('ae')): connection.send_msg(user.title() + ': ' + getinfo.get_ae()) #get truces elif text.startswith(commands.get('truces')): connection.send_msg(user.title() + ': ' + getinfo.get_truces())
class Mib: """ Main class which handles most of the core functionality. """ def __init__(self): """ Initialize variables and read config. """ sys.path.append("plugins") self.loaded_plugins = {} # plugin name : module self.cmd_callbacks = {} # command : set(function) self.privmsg_cmd_callbacks = {} # command : set(function) self.command_masks = {} # command : list(regexp) self.plugins = set(config.LOAD_PLUGINS) self.cmd_prefixes = set(config.CMD_PREFIXES) self.nick = config.NICK self.username = config.USERNAME self.realname = config.REALNAME self.server, self.port = config.SERVER self.channels = config.CHANNELS self.socket = IrcSocket(self.server, self.port, self.nick, self.username, self.realname) self.socket.register_readline_cb(self.parse_line) for channel in self.channels: self.socket.join(channel) for plugin in self.plugins: print self.load_plugin(plugin)[1] def run(self): """ Start socket's main loop. """ self.socket.run() def clean(self): for plugin in self.loaded_plugins.itervalues(): plugin.clean() def parse_line(self, line): """ Parse line and call callbacks registered for command. """ print line parsed = parse(line) if not parsed: print 'Unable to parse line: "%s"' % (line) return # call registered functions for function in self.cmd_callbacks.get(parsed.cmd, ()): try: function(parsed) except Exception, e: print "Error from function", repr(function), ":", e # call registered privmsg functions with pre-parsed line if parsed.cmd == "PRIVMSG": cmd_prefix = parsed.postfix.split(" ", 1)[0] postfix = parsed.postfix[len(cmd_prefix) :].lstrip() if cmd_prefix in self.cmd_prefixes: print "Found command prefix", cmd_prefix cmd = postfix.lstrip().split(" ", 1)[0] postfix = postfix[len(cmd) :].lstrip() stripped_parsed = IRCMsg(parsed.prefix, parsed.cmd, parsed.params, postfix) print "stripped_parsed = ", stripped_parsed print "Searching for command", cmd for function in self.privmsg_cmd_callbacks.get(cmd, ()): run = False if cmd not in self.command_masks: run = True else: print "There are limitations for this command" for regexp in self.command_masks[cmd]: print "Matching %s to %s" % (parsed.prefix, regexp.pattern) if regexp.match(parsed.prefix): run = True break if run: try: print "Executing command %s" % cmd function(stripped_parsed) except Exception, e: print "Error from function", repr(function), ":", e
class Irc: """A class to manage channels and users on one IRC network This class is a wrapper for the IrcSocket class """ def get_messages(self, stop, buffer): while 1: if stop: logging.info('[IRC] Receive thread sent stop signal') break try: lines = self.socket.get_raw() for line in lines: # Handle ping and pong here if line[0:4] == 'PING': self.send_raw('PONG' + line[4:]) logging.debug('Sent pong successfully') continue buffer.put(line) except OSError as err: logging.error(err) if self.connected: self.buffer.put(f'>>Error receiving messages: {err}') self.disconnect() logging.info('[IRC] Socket error in receive thread, stopping...') break def __init__(self, host, port, nick, user, real, get_messages_callback, buffer, tag=False): """Create a new IRC instance Each instance represents one connection to one server""" self.host = host self.port = port self.nick = nick self.user = user self.real = real self.channels = [] self.get_messages_callback = get_messages_callback self.buffer = buffer self.connected = False # Assign server tag if none given # This works well for host names, is not great for IPs but oh well if not tag: try: self.tag = host.split('.')[:-2] except IndexError: self.tag = host def connect(self): # Try to connect if self.connected: buffer.put('>>We are already connected') try: self.socket = IrcSocket() self.socket.connect(self.host, self.port) self.socket.put_raw(f"USER {self.user} 0 * :{self.real}") # TODO Support alternate nick self.socket.put_raw(f"NICK {self.nick}") self.stop_thread = False # used to stop the thread when connection dies self.receive_thread = threading.Thread(target=self.get_messages, args=(self.stop_thread, self.buffer,), daemon=True) self.receive_thread.start() self.connected = True except OSError as err: logging.error(err) self.buffer.put(f'>>Connection failed due to error: {err}') self.disconnect() def disconnect(self): """Shut down the socket and run clean up code""" try: logging.debug('[IRC] Disconnection process started') self.connected = False self.stop_thread = True # failsafe self.socket.disconnect() except OSError as err: logging.warning('[IRC] IRC socket reported error closing.') finally: logging.info('[IRC] IRC connection closed') logging.debug('[IRC] Disconnection process finished') self.buffer.put('>>IRC connection lost') self.buffer.put('[wiggleVerse] DROPCON') def send_raw(self, message): try: self.socket.put_raw(message) except OSError as err: logging.error(f"[IRC] Error sending: {err}") buffer.put(f'>>Error sending message: {err}') buffer.put('Disconnecting...') self.disconnect() def is_connected(self): return self.connected def get_tag(self): return self.tag