# -*- coding:utf-8 -*- import socket import re from time import sleep class noaIRC(object): def __init__(self, host, port, user, key, channel): """ Authentificate the bot over Twitch IRC """ self.__channel = channel self.__compiledBanWords = [] # configure socket and try to join IRC channel self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.__sock.connect((host, port)) self.__sock.settimeout(1) self.__sock.send("PASS {}\r\n".format(key).encode("utf-8")) self.__sock.send("NICK {}\r\n".format(user).encode("utf-8")) self.__sock.send("JOIN {}\r\n".format(channel).encode("utf-8")) def setPattern(self, pattern): """ Allow to set message pattern in order to check whether the posted message is a real message and not service message """ self.__message_pattern = re.compile(r"%s" % pattern) def setMySQLconnector(self, connector): """ Allow to set mysql connector get persistance """ self.__mysql = connector def __getAllowedCommands(self, command): rights = { "ban" : ["admin"], "rban" : ["admin"], "quote" : ["admin", "default"] } return rights[command] if command in rights.keys() else None def __isAuthorized(self, command, username): """ Return whether user is authorized to use command """ # Get user role allowedGroups = self.__getAllowedCommands(command) if not allowedGroups: return False if 'default' in allowedGroups: return True for allowedGroup in allowedGroups: if username in self.__mysql.getUsers()[allowedGroup]: return True def __chat(self, msg): """ Send a chat message to the server. Keyword arguments: sock -- the socket over which to send the message msg -- the message to be sent """ self.__sock.send("PRIVMSG %s :%s\r\n" % (self.__channel, msg.encode('utf-8'))) def __timeout(self, username, timeout=5): """ Timeout a user """ self.__chat(u"Timeout %ds %s (warning)" % (timeout, username)) self.__sock.send("PRIVMSG %s :/timeout %s 5 \r\n" % (self.__channel, username)) def __call(self, command, parameters, username): """ Execute a command """ if not self.__isAuthorized(command, username): return # Remove final carriage return parameters = parameters.replace("\r", "") # Moderation if command == 'ban' and len(parameters) : banword = parameters.split(' ')[0].replace("\r", "") if banword in ['***', '']: return self.__compiledBanWords.append(re.compile(r'%s'%(banword))) self.__mysql.addSwearword(banword) self.__chat(u"Mot interdit ajouté") if command == "rban" and len(parameters): banword = parameters.split(' ')[0] index = self.__mysql.delSwearword(banword) if index is not None: del self.__compiledBanWords[index] self.__chat(u"Mot interdit supprimé") # Quoting system if command == 'quote' and len(parameters) : if parameters.startswith("#"): index = int(parameters[1:]) - 1 if index < 0: return message = self.__mysql.getQuote(index) if message: self.__chat(message) else: self.__mysql.addQuote(parameters) def __parseMessage(self, message, username): """ Check message """ # check swearword groups = self.__mysql.getUsers() for swearword in self.__compiledBanWords: if swearword.search(message) is not None and not username in groups['admin'] and not username in groups['moderator']: self.__timeout(username) # command pattern command_pattern = re.compile(r'^!(\w+)\s?(.*)') matches = re.search(command_pattern, message) if matches: command = matches.group(1) parameters = matches.group(2) self.__call(command, parameters, username) def run(self): """ Core loop """ # Compile ban patterns for banword in self.__mysql.getSwearwords(): self.__compiledBanWords.append(re.compile(r'%s'%(banword))) while True: try: response = self.__sock.recv(1024).decode("utf-8") except socket.error, e: continue else: if response == "PING :tmi.twitch.tv\r\n": self.__sock.send("PONG :tmi.twitch.tv\r\n".encode("utf-8")) print "pong" else: matches = re.search(self.__message_pattern, response) if matches: username = matches.group(1) message = matches.group(2) self.__parseMessage(message, username) sleep(0.1)