def dispatch(self, origin, text, args): bytes = text event = args[0] args = args[1:] for priority in ('high', 'medium', 'low'): items = self.commands[priority].items() for regexp, funcs in items: for func in funcs: if event != func.event: continue match = regexp.match(text) if match: if self.limit(origin, func): continue willie = self.WillieWrapper(self, origin) trigger = self.Trigger(text, origin, bytes, match, event, args, self) nick = (trigger.nick).lower() ## blocking ability bad_nicks = self.config.core.get_list('nick_blocks') bad_masks = self.config.core.get_list('host_blocks') if len(bad_masks) > 0: for hostmask in bad_masks: hostmask = hostmask.replace("\n", "") if len(hostmask) < 1: continue re_temp = re.compile(hostmask) host = origin.host host = host.lower() if re_temp.findall(host) or hostmask in host: return if len(bad_nicks) > 0: for nick in bad_nicks: nick = nick.replace("\n", "") if len(nick) < 1: continue re_temp = re.compile(nick) #RFC-lowercasing the regex is impractical. So #we'll just specify to use RFC-lowercase in the #regex, which means we'll have to be in RFC- #lowercase here. if (re_temp.findall(trigger.nick.lower()) or Nick(nick).lower() in trigger.nick.lower()): return if func.thread: targs = (func, origin, willie, trigger) t = threading.Thread(target=self.call, args=targs) t.start() else: self.call(func, origin, willie, trigger)
def _nick_blocked(self, nick): bad_nicks = self.config.core.get_list('nick_blocks') for bad_nick in bad_nicks: bad_nick = bad_nick.strip() if not bad_nick: continue if (re.match(bad_nick + '$', nick, re.IGNORECASE) or Nick(bad_nick) == nick): return True return False
def __init__(self, config): if config.ca_certs is not None: ca_certs = config.ca_certs else: ca_certs = '/etc/pki/tls/cert.pem' if config.log_raw is None: #Default is to log raw data, can be disabled in config config.log_raw = True asynchat.async_chat.__init__(self) self.set_terminator('\n') self.buffer = '' self.nick = Nick(config.nick) """Willie's current ``Nick``. Changing this while Willie is running is untested.""" self.user = config.user """Willie's user/ident.""" self.name = config.name """Willie's "real name", as used for whois.""" self.channels = [] """The list of channels Willie is currently in.""" self.stack = [] self.ca_certs = ca_certs self.hasquit = False self.sending = threading.RLock() self.writing_lock = threading.Lock() self.raw = None #Right now, only accounting for two op levels. #This might be expanded later. #These lists are filled in startup.py, as of right now. self.ops = dict() """ A dictionary mapping channels to a ``Nick`` list of their operators. """ self.halfplus = dict() """ A dictionary mapping channels to a ``Nick`` list of their half-ops and ops. """ self.voices = dict() """ A dictionary mapping channels to a ``Nick`` list of their voices, half-ops and ops. """ #We need this to prevent error loops in handle_error self.error_count = 0 self.connection_registered = False """ Set to True when a server has accepted the client connection and
def __init__(self, bot, source, args, tags): self.hostmask = source self.tags = tags #Split out the nick, user, and host from hostmask per the regex above. match = Origin.source.match(source or '') self.nick, self.user, self.host = match.groups() self.nick = Nick(self.nick) # If we have more than one argument, the second one is the sender if len(args) > 1: target = Nick(args[1]) else: target = None # Unless we're messaging the bot directly, in which case that second # arg will be our bot's name. if target and target.lower() == bot.nick.lower(): target = self.nick self.sender = target
def __init__(self, bot, source, args): self.hostmask = source match = Origin.source.match(source or '') self.nick, self.user, self.host = match.groups() self.nick = Nick(self.nick) if len(args) > 1: target = args[1] else: target = None if target and target.lower() == bot.nick.lower(): target = self.nick self.sender = target
def __init__(self, bot, source, args): self.hostmask = source #Split out the nick, user, and host from hostmask per the regex above. match = Origin.source.match(source or '') self.nick, self.user, self.host = match.groups() self.nick = Nick(self.nick) # If we have more than one argument, the second one is the sender if len(args) > 1: target = args[1] else: target = None # Unless we're messaging the bot directly, in which case that second # arg will be our bot's name. if target and target.lower() == bot.nick.lower(): target = self.nick self.sender = target
def __init__(self): asynchat.async_chat.__init__(self) self.set_terminator('\n') self.error_count = 0 self.last_error_timestamp = datetime.now() self.buffer = '' self.nick = Nick(settings.BOT_NICK) self.ident = settings.BOT_IDENT self.name = settings.BOT_NAME self.log = logger() self.stack = [] self.channels = [] self.ca_certs = '/etc/pki/tls/cert.pem' self.has_quit = False self.sending = threading.RLock() self.writing_lock = threading.Lock() self.last_ping_time = None self.raw = None self.ssl = None
def del_voice(self, channel, name): self.voices[channel].discard(Nick(name))
def del_halfop(self, channel, name): self.halfplus[channel].discard(Nick(name))
def del_op(self, channel, name): self.ops[channel].discard(Nick(name))
def add_voice(self, channel, name): if isinstance(name, Nick): self.voices[channel].add(name) else: self.voices[channel].add(Nick(name))
def add_halfop(self, channel, name): if isinstance(name, Nick): self.halfplus[channel].add(name) else: self.halfplus[channel].add(Nick(name))
def add_op(self, channel, name): if isinstance(name, Nick): self.ops[channel].add(name) else: self.ops[channel].add(Nick(name))
def __new__(cls, text, origin, bytes, match, event, args, self): s = unicode.__new__(cls, text) s.raw = origin.raw s.sender = origin.sender """ The channel (or nick, in a private message) from which the message was sent. """ s.hostmask = origin.hostmask """ Hostmask of the person who sent the message in the form <nick>!<user>@<host> """ s.user = origin.user """Local username of the person who sent the message""" s.nick = origin.nick """The ``Nick`` of the person who sent the message.""" s.event = event """ The IRC event (e.g. ``PRIVMSG`` or ``MODE``) which triggered the message.""" s.bytes = bytes """ The text which triggered the message. Equivalent to ``Trigger.group(0)``. """ s.match = match """ The regular expression ``MatchObject_`` for the triggering line. .. _MatchObject: http://docs.python.org/library/re.html#match-objects """ s.group = match.group """The ``group`` function of the ``match`` attribute. See Python ``re_`` documentation for details.""" s.groups = match.groups """The ``groups`` function of the ``match`` attribute. See Python ``re_`` documentation for details.""" s.args = args """ A tuple containing each of the arguments to an event. These are the strings passed between the event name and the colon. For example, setting ``mode -m`` on the channel ``#example``, args would be ``('#example', '-m')`` """ if len(self.config.core.get_list('admins')) > 0: s.admin = (origin.nick in [ Nick(n) for n in self.config.core.get_list('admins') ]) else: s.admin = False """ True if the nick which triggered the command is in Willie's admin list as defined in the config file. """ # Support specifying admins by hostnames if not s.admin and len(self.config.core.get_list('admins')) > 0: for each_admin in self.config.core.get_list('admins'): re_admin = re.compile(each_admin) if re_admin.findall(origin.host): s.admin = True elif '@' in each_admin: temp = each_admin.split('@') re_host = re.compile(temp[1]) if re_host.findall(origin.host): s.admin = True if not self.config.core.owner: s.owner = False elif '@' in self.config.core.owner: s.owner = origin.nick + '@' + \ origin.host == self.config.core.owner else: s.owner = (origin.nick == Nick(self.config.core.owner)) # Bot owner inherits all the admin rights, therefore is considered # admin s.admin = s.admin or s.owner s.host = origin.host if s.sender is not s.nick: # no ops in PM s.ops = self.ops.get(s.sender, []) """ List of channel operators in the channel the message was recived in """ s.halfplus = self.halfplus.get(s.sender, []) """ List of channel half-operators in the channel the message was recived in """ s.isop = (s.nick in s.ops or s.nick in s.halfplus) """True if the user is half-op or an op""" s.voices = self.voices.get(s.sender, []) """ List of channel operators in the channel the message was recived in """ s.isvoice = (s.nick in s.ops or s.nick in s.halfplus or s.nick in s.voices) """True if the user is voiced, has op, or has half-op""" else: s.isop = False s.isvoice = False s.ops = [] s.halfplus = [] s.voices = [] return s