def ban(bot, trigger): """ This give admins the ability to ban a user. The bot must be a Channel Operator for this command to work. """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("Non sono OP :(") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) banmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return channel = opt banmask = text[2] banmask = configureHostMask(banmask) if banmask == '': return bot.write(['MODE', channel, '+b', banmask])
def track_nicks(bot, trigger): """Track nickname changes and maintain our chanops list accordingly.""" old = trigger.nick new = Nick(trigger) # Give debug mssage, and PM the owner, if the bot's own nick changes. if old == bot.nick: privmsg = "Hi, I'm your bot, %s." + \ " Something has made my nick change." + \ " This can cause some problems for me," + \ " and make me do weird things." + \ " You'll probably want to restart me," + \ " and figure out what made that happen" + \ " so you can stop it happening again." + \ " (Usually, it means you tried to give me a nick" + \ " that's protected by NickServ.)" % bot.nick debug_msg = "Nick changed by server." + \ " This can cause unexpected behavior. Please restart the bot." bot.debug(__file__, debug_msg, 'always') bot.msg(bot.config.core.owner, privmsg) return for channel in bot.privileges: channel = Nick(channel) if old in bot.privileges[channel]: value = bot.privileges[channel].pop(old) bot.privileges[channel][new] = value
def ban(bot, trigger): """ This give admins the ability to ban a user. The bot must be a Channel Operator for this command to work. """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("I'm not a channel operator!") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) banmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return channel = opt banmask = text[2] banmask = configureHostMask(banmask) if banmask == '': return bot.write(['MODE', channel, '+b', banmask])
def kick(bot, trigger): """ Kick a user from the channel. """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("I'm not a channel operator!") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) nick = opt channel = trigger.sender reasonidx = 2 if not opt.is_nick(): if argc < 3: return nick = text[2] channel = opt reasonidx = 3 reason = ' '.join(text[reasonidx:]) if nick != bot.config.nick: bot.write(['KICK', channel, nick, reason])
def kickban(bot, trigger): """ This gives admins the ability to kickban a user. The bot must be a Channel Operator for this command to work. .kickban [#chan] user1 user!*@* get out of here """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("I'm not a channel operator!") text = trigger.group().split() argc = len(text) if argc < 4: return opt = Nick(text[1]) nick = opt mask = text[2] reasonidx = 3 if not opt.is_nick(): if argc < 5: return channel = opt nick = text[2] mask = text[3] reasonidx = 4 reason = ' '.join(text[reasonidx:]) mask = configureHostMask(mask) if mask == '': return bot.write(['MODE', channel, '+b', mask]) bot.write(['KICK', channel, nick, ' :', reason])
def kick(bot, trigger): """ Kick a user from the channel. """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("Non sono OP :(") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) nick = opt channel = trigger.sender reasonidx = 2 if not opt.is_nick(): if argc < 3: return nick = text[2] channel = opt reasonidx = 3 reason = '_'.join(text[reasonidx:]) if nick != bot.config.nick: bot.write(['KICK', channel, nick, reason])
def collectlines(bot, trigger): """Create a temporary log of what people say""" # Don't log things in PM if not trigger.sender.startswith('#'): return # Add a log for the channel and nick, if there isn't already one if trigger.sender not in bot.memory['find_lines']: bot.memory['find_lines'][trigger.sender] = WillieMemory() if Nick(trigger.nick) not in bot.memory['find_lines'][trigger.sender]: bot.memory['find_lines'][trigger.sender][Nick(trigger.nick)] = list() # Create a temporary list of the user's lines in a channel templist = bot.memory['find_lines'][trigger.sender][Nick(trigger.nick)] line = trigger.group() if line.startswith("s/"): # Don't remember substitutions return elif line.startswith("\x01ACTION"): # For /me messages line = line[:-1] templist.append(line) else: templist.append(line) del templist[:-10] # Keep the log to 10 lines per person bot.memory['find_lines'][trigger.sender][Nick(trigger.nick)] = templist
def kickban(bot, trigger): """ This gives admins the ability to kickban a user. The bot must be a Channel Operator for this command to work .kickban [#chan] user1 user!*@* get out of here """ if (not trigger.owner) and (not trigger.admin) and (bot.privileges[trigger.sender][trigger.nick] < OP): return text = trigger.group().split() argc = len(text) if argc < 4: return opt = Nick(text[1]) nick = opt mask = text[2] reasonidx = 3 if not opt.is_nick(): if argc < 5: return channel = opt nick = text[2] mask = text[3] reasonidx = 4 reason = ' '.join(text[reasonidx:]) mask = configureHostMask(mask) if mask == '': return bot.write(['MODE', channel, '+b', mask]) bot.write(['KICK', channel, nick, ' :', reason])
def kick(bot, trigger): """ Echa a un usuario del canal actual """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("No soy un operador del canal!") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) nick = opt channel = trigger.sender reasonidx = 2 if not opt.is_nick(): if argc < 3: return nick = text[2] channel = opt reasonidx = 3 reason = ' '.join(text[reasonidx:]) if nick != bot.config.nick: bot.write(['KICK', channel, nick, reason])
def kickban(bot, trigger): """ Echa y veta a un usuario o máscara %kickban [#chan] user1 user!*@* fuera de aquí """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("No soy operador de este canal!!") text = trigger.group().split() argc = len(text) if argc < 4: return opt = Nick(text[1]) nick = opt mask = text[2] reasonidx = 3 if not opt.is_nick(): if argc < 5: return channel = opt nick = text[2] mask = text[3] reasonidx = 4 reason = ' '.join(text[reasonidx:]) mask = configureHostMask(mask) if mask == '': return bot.write(['MODE', channel, '+b', mask]) bot.write(['KICK', channel, nick, ' :', reason])
def unquiet(bot, trigger): """ This gives admins the ability to unquiet a user. The bot must be a Channel Operator for this command to work. """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < OP: return bot.reply("I'm not a channel operator!") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) quietmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return quietmask = text[2] channel = opt quietmask = configureHostMask(quietmask) if quietmask == '': return bot.write(['MODE', opt, '-q', quietmask])
def unquiet(bot, trigger): """ This gives admins the ability to unquiet a user. The bot must be a Channel Operator for this command to work. """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < OP: return bot.reply("Non sono OP :(") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) quietmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return quietmask = text[2] channel = opt quietmask = configureHostMask(quietmask) if quietmask == '': return bot.write(['MODE', opt, '-q', quietmask])
def track_modes(bot, trigger): """Track usermode changes and keep our lists of ops up to date.""" # Mode message format: <channel> *( ( "-" / "+" ) *<modes> *<modeparams> ) channel = Nick(trigger.args[0]) line = trigger.args[1:] # If the first character of where the mode is being set isn't a # # then it's a user mode, not a channel mode, so we'll ignore it. if channel.is_nick(): return def handle_old_modes(nick, mode): #Old mode maintenance. Drop this crap in 5.0. if mode[1] == 'o' or mode[1] == 'q' or mode[1] == 'a': if mode[0] == '+': bot.add_op(channel, nick) else: bot.del_op(channel, nick) elif mode[1] == 'h': # Halfop if mode[0] == '+': bot.add_halfop(channel, nick) else: bot.del_halfop(channel, nick) elif mode[1] == 'v': if mode[0] == '+': bot.add_voice(channel, nick) else: bot.del_voice(channel, nick) mapping = {'v': willie.module.VOICE, 'h': willie.module.HALFOP, 'o': willie.module.OP, 'a': willie.module.ADMIN, 'q': willie.module.OWNER} modes = [] for arg in line: if arg[0] in '+-': # There was a comment claiming IRC allows e.g. MODE +aB-c foo, but # I don't see it in any RFCs. Leaving in the extra parsing for now. sign = '' modes = [] for char in arg: if char == '+' or char == '-': sign = char else: modes.append(sign + char) else: arg = Nick(arg) for mode in modes: priv = bot.privileges[channel].get(arg, 0) value = mapping.get(mode[1]) if value is not None: if mode[0] == '+': priv = priv | value else: priv = priv & ~value bot.privileges[channel][arg] = priv handle_old_modes(arg, mode)
def handle(willie, trigger): """ Associates your IRC nick with a Twitter handle. Example: .handle @egdelwonk """ # prevent blocked users from accessing the trigger if trigger.nick in willie.config.core.nick_blocks: return nick_target = trigger.group(2) handle_match_re = re.compile(r'@([A-Za-z0-9_]+)') updated_handle = re.findall(handle_match_re, trigger) if willie.db and updated_handle: # update the triggering nickname's twitter handle willie.db.preferences.update(Nick(trigger.nick), {'twitter_handle': updated_handle[0]}) willie.say( Nick(trigger.nick) + ': your twitter handle is now @' + updated_handle[0]) elif nick_target: # establish nick target nick_target = Nick(nick_target.strip()) # return saved handle nick_handle = get_handle(willie, nick_target) # targeted nickname has a saved twitter handle if nick_handle: willie.say( Nick(trigger.nick) + ': ' + nick_target + '\'s twitter handle is: @' + nick_handle + ' / http://twitter.com/' + nick_handle) # targeted nickname does not exists in usersdb preferences else: willie.say( Nick(trigger.nick) + ': ' + nick_target + ' does not have a twitter handle saved yet.') # no additional message was passed to the trigger else: nick_handle = get_handle(willie, Nick(trigger.nick)) if nick_handle: willie.say( Nick(trigger.nick) + ': ' + 'your twitter handle is @' + nick_handle) else: willie.say( Nick(trigger.nick) + ': ' + 'your twitter handle has not been saved yet.')
def f_remind(bot, trigger): """Give someone a message the next time they're seen""" teller = trigger.nick verb = trigger.group(1) if not trigger.group(3): bot.reply("%s whom?" % verb) return tellee = trigger.group(3).rstrip('.,:;') msg = trigger.group(2).lstrip(tellee).lstrip() if not msg: bot.reply("%s %s what?" % (verb, tellee)) return tellee = Nick(tellee) if not os.path.exists(bot.tell_filename): return if len(tellee) > 20: return bot.reply('That nickname is too long.') if tellee == bot.nick: return bot.reply("I'm here now, you can tell me whatever you want!") if not tellee in (Nick(teller), bot.nick, 'me'): tz = willie.tools.get_timezone(bot.db, bot.config, None, tellee) timenow = willie.tools.format_time(bot.db, bot.config, tz, tellee) bot.memory['tell_lock'].acquire() try: if not tellee in bot.memory['reminders']: bot.memory['reminders'][tellee] = [(teller, verb, timenow, msg) ] else: bot.memory['reminders'][tellee].append( (teller, verb, timenow, msg)) finally: bot.memory['tell_lock'].release() response = "I'll pass that on when %s is around." % tellee bot.reply(response) elif Nick(teller) == tellee: bot.say('You can %s yourself that.' % verb) else: bot.say("Hey, I'm not as stupid as Monty you know!") dumpReminders(bot.tell_filename, bot.memory['reminders'], bot.memory['tell_lock']) # @@ tell
def f_remind(willie, trigger): teller = trigger.nick verb, tellee, msg = trigger.groups() verb = unicode(verb) tellee = Nick(tellee.rstrip('.,:;')) msg = unicode(msg) if not os.path.exists(willie.tell_filename): return if len(tellee) > 20: return willie.reply('That nickname is too long.') if tellee == willie.nick: return willie.reply("I'm here now, you can tell me whatever you want!") tz, tformat = get_user_time(willie, tellee) print tellee, tz, tformat timenow = datetime.datetime.now(tz).strftime(tformat) if not tellee in (Nick(teller), willie.nick, 'me'): willie.memory['tell_lock'].acquire() try: if not willie.memory['reminders'].has_key(tellee): willie.memory['reminders'][tellee] = [(teller, verb, timenow, msg)] else: willie.memory['reminders'][tellee].append((teller, verb, timenow, msg)) finally: willie.memory['tell_lock'].release() responses = [ "%s doesn't care, but I'll force it in conversation.", "%s is probably just ignoring you.", "Sure, I'll tell %s that right after you go outside once for in your life.", "Sure says something when %s gives me more attention than they give you, doesn't it?", "Sure, fine, whatever. I'll leave %s your message.", "Alright, but I apologize in advance if %s just doesn't care.", "Alright, next time I see %s I'll tell them that, just so you don't have to worry about spilling spaghetti on yourself.", "I'll leave that with %s. Later. If I feel like it.", "Aaalright, if you insist, but %s probably thinks you're just drunk right now.", ] response = random.choice(responses) % tellee willie.reply(response) elif Nick(teller) == tellee: willie.say("Look at me, I'm %s and I'm super clever at breaking IRC bots! I'm oozing cleverness!" % teller) else: willie.say("Hey, I'm not as stupid as Monty you know!") dumpReminders(willie.tell_filename, willie.memory['reminders'], willie.memory['tell_lock']) # @@ tell
def handle(willie, trigger): """ Associates your IRC nick with a Twitter handle. Example: .handle @egdelwonk """ # prevent blocked users from accessing the trigger if trigger.nick in willie.config.core.nick_blocks: return nick_target = trigger.group(2) handle_match_re = re.compile(r'@([A-Za-z0-9_]+)') updated_handle = re.findall(handle_match_re, trigger) if willie.db and updated_handle: # update the triggering nickname's twitter handle willie.db.preferences.update(Nick(trigger.nick), { 'twitter_handle': updated_handle[0]}) willie.say( Nick(trigger.nick) + ': your twitter handle is now @' + updated_handle[0]) elif nick_target: # establish nick target nick_target = Nick(nick_target.strip()) # return saved handle nick_handle = get_handle(willie, nick_target) # targeted nickname has a saved twitter handle if nick_handle: willie.say( Nick(trigger.nick) + ': ' + nick_target + '\'s twitter handle is: @' + nick_handle + ' / http://twitter.com/' + nick_handle) # targeted nickname does not exists in usersdb preferences else: willie.say( Nick(trigger.nick) + ': ' + nick_target + ' does not have a twitter handle saved yet.') # no additional message was passed to the trigger else: nick_handle = get_handle(willie, Nick(trigger.nick)) if nick_handle: willie.say(Nick(trigger.nick) + ': ' + 'your twitter handle is @' + nick_handle) else: willie.say(Nick( trigger.nick) + ': ' + 'your twitter handle has not been saved yet.')
def track_nicks(bot, trigger): '''Track nickname changes and maintain our chanops list accordingly''' old = trigger.nick new = Nick(trigger) # Give debug mssage, and PM the owner, if the bot's own nick changes. if old == bot.nick: privmsg = "Hi, I'm your bot, %s. Something has made my nick change. This can cause some problems for me, and make me do weird things. You'll probably want to restart me, and figure out what made that happen so you can stop it happening again. (Usually, it means you tried to give me a nick that's protected by NickServ.)" % bot.nick debug_msg = "Nick changed by server. This can cause unexpected behavior. Please restart the bot." bot.debug('[CORE]', debug_msg, 'always') bot.msg(bot.config.core.owner, privmsg) return for channel in bot.halfplus: if old in bot.halfplus[channel]: bot.del_halfop(channel, old) bot.add_halfop(channel, new) for channel in bot.ops: if old in bot.ops[channel]: bot.del_op(channel, old) bot.add_op(channel, new) for channel in bot.voices: if old in bot.voices[channel]: bot.del_voice(channel, old) bot.add_voice(channel, new)
def msg(self, recipient, text, max_messages=1): # We're arbitrarily saying that the max is 400 bytes of text when # messages will be split. Otherwise, we'd have to acocunt for the bot's # hostmask, which is hard. max_text_length = 400 # Encode to bytes, for propper length calculation if isinstance(text, unicode): encoded_text = text.encode('utf-8') else: encoded_text = text excess = '' if max_messages > 1 and len(encoded_text) > max_text_length: last_space = encoded_text.rfind(' ', 0, max_text_length) if last_space == -1: excess = encoded_text[max_text_length:] encoded_text = encoded_text[:max_text_length] else: excess = encoded_text[last_space + 1:] encoded_text = encoded_text[:last_space] # We'll then send the excess at the end # Back to unicode again, so we don't screw things up later. text = encoded_text.decode('utf-8') try: self.sending.acquire() # No messages within the last 3 seconds? Go ahead! # Otherwise, wait so it's been at least 0.8 seconds + penalty recipient_id = Nick(recipient) if recipient_id not in self.stack: self.stack[recipient_id] = [] elif self.stack[recipient_id]: elapsed = time.time() - self.stack[recipient_id][-1][0] if elapsed < 3: penalty = float(max(0, len(text) - 50)) / 70 wait = 0.7 + penalty if elapsed < wait: time.sleep(wait - elapsed) # Loop detection messages = [m[1] for m in self.stack[recipient_id][-8:]] # If what we about to send repeated at least 5 times in the # last 2 minutes, replace with '...' if messages.count(text) >= 5 and elapsed < 120: text = '...' if messages.count('...') >= 3: # If we said '...' 3 times, discard message return self.write(('PRIVMSG', recipient), text) self.stack[recipient_id].append((time.time(), self.safe(text))) self.stack[recipient_id] = self.stack[recipient_id][-10:] finally: self.sending.release() # Now that we've sent the first part, we need to send the rest. Doing # this recursively seems easier to me than iteratively if excess: self.msg(recipient, excess, max_messages - 1)
def writeChannelMessage(trigger): # prepares a channel message and calls writeLogFile with it nick = Nick(trigger.nick) message = prepareMessage(trigger) fn = conf.get('main', 'basedir') + conf.get('main', 'nicksdir') + \ nick + '/' + nick writeLogFile(fn, message)
def msg(bot, trigger): if trigger.sender.startswith('#'): return nick = Nick(trigger.sender) pw_plain = sanitize(trigger.group(1)) hashed = hashPW(pw_plain) address = sanitize(trigger.group(2)) rpc = conf._sections['rpc'] conn = bitcoinrpc.connect_to_remote(rpc['user'], rpc['pass'], \ rpc['host'], rpc['port']) rv = conn.validateaddress(address) if not rv.isvalid: bot.reply('invalid address, try again!') return updatePasswords() global passwords if nick in passwords: if not hashed == passwords[nick]: bot.reply('incorrect password.') return else: appendPasswordFile(nick + ' ' + hashPW(pw_plain)) updateAddresses() global addresses if nick in addresses: if address == addresses[nick]: bot.reply(conf.get('main', 'addressexistsreply')) return else: bot.reply('Updating your stored address') updateAddressFile(nick, address) logging.info("set address for %s to %s" % (nick, address)) bot.reply(conf.get('main', 'walletreply') % (nick, address, pw_plain))
def track_kick(bot, trigger): nick = Nick(trigger.args[1]) if nick == bot.nick: bot.channels.remove(trigger.sender) del bot.privileges[trigger.sender] else: del bot.privileges[trigger.sender][nick]
def __init__(self, config): ca_certs = '/etc/pki/tls/cert.pem' if config.ca_certs is not None: ca_certs = config.ca_certs elif not os.path.isfile(ca_certs): ca_certs = '/etc/ssl/certs/ca-certificates.crt' if not os.path.isfile(ca_certs): stderr('Could not open CA certificates file. SSL will not ' 'work properly.') 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(b'\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 helpmsg(bot, trigger): if trigger.sender.startswith('#'): return nick = Nick(trigger.sender) logging.info('got help command from %s' % nick) for r in (conf.get('main', 'help1'), conf.get('main', 'help2'), \ conf.get('main', 'help3')): bot.reply(r)
def f_optout(willie, trigger): """ check to see if i've opted in. """ nick = Nick(trigger.nick) if not optin_check(willie, Nick(trigger.nick)): willie.say( '{nick}: You have not opted in, ignoring your links.'.format( nick=nick)) return willie.db.preferences.update( nick, { 'optin_auto_tweet': '', 'optin_auto_tweet_date': str(datetime.datetime.today()) }) willie.say( '{nick}: You have opted out, ignoring your links.'.format(nick=nick)) return
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 f_remind(bot, trigger): """Give someone a message the next time they're seen""" teller = trigger.nick verb = trigger.group(1) tellee, msg = trigger.group(2).split(None, 1) tellee = Nick(tellee.rstrip('.,:;')) if not os.path.exists(bot.tell_filename): return if len(tellee) > 20: return bot.reply('That nickname is too long.') if tellee == bot.nick: return bot.reply("I'm here now, you can tell me whatever you want!") tz, tformat = get_user_time(bot, tellee) print tellee, tz, tformat timenow = datetime.datetime.now(tz).strftime(tformat) if not tellee in (Nick(teller), bot.nick, 'me'): bot.memory['tell_lock'].acquire() try: if not tellee in bot.memory['reminders']: bot.memory['reminders'][tellee] = [(teller, verb, timenow, msg) ] else: bot.memory['reminders'][tellee].append( (teller, verb, timenow, msg)) finally: bot.memory['tell_lock'].release() response = "I'll pass that on when %s is around." % tellee bot.reply(response) elif Nick(teller) == tellee: bot.say('You can %s yourself that.' % verb) else: bot.say("Hey, I'm not as stupid as Monty you know!") dumpReminders(bot.tell_filename, bot.memory['reminders'], bot.memory['tell_lock']) # @@ tell
def handle_names(bot, trigger): """Handle NAMES response, happens when joining to channels.""" names = trigger.split() #TODO specific to one channel type. See issue 281. channels = re.search('(#\S*)', bot.raw) if not channels: return channel = Nick(channels.group(1)) if channel not in bot.privileges: bot.privileges[channel] = dict() bot.init_ops_list(channel) # This could probably be made flexible in the future, but I don't think # it'd be worth it. mapping = { '+': willie.module.VOICE, '%': willie.module.HALFOP, '@': willie.module.OP, '&': willie.module.ADMIN, '~': willie.module.OWNER } for name in names: priv = 0 for prefix, value in iteritems(mapping): if prefix in name: priv = priv | value nick = Nick(name.lstrip(''.join(mapping.keys()))) bot.privileges[channel][nick] = priv # Old op list maintenance is down here, and should be removed at some # point if '@' in name or '~' in name or '&' in name: bot.add_op(channel, name.lstrip('@&%+~')) bot.add_halfop(channel, name.lstrip('@&%+~')) bot.add_voice(channel, name.lstrip('@&%+~')) elif '%' in name: bot.add_halfop(channel, name.lstrip('@&%+~')) bot.add_voice(channel, name.lstrip('@&%+~')) elif '+' in name: bot.add_voice(channel, name.lstrip('@&%+~'))
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 f_optin(willie, trigger): """ opt in to auto tweeting links posted. """ # prevent blocked users from accessing the trigger if trigger.nick in willie.config.core.nick_blocks: return if not willie.db: return willie.db.preferences.update(Nick(trigger.nick), { 'optin_auto_tweet': 'yes', }) willie.db.preferences.update( Nick(trigger.nick), { 'optin_auto_tweet_date': str(datetime.datetime.today()), }) willie.say( '{nick}: You are now opted in to auto-tweet links you post to @nashdevbot. Thx!' .format(nick=Nick(trigger.nick)))
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 f_remind(willie, trigger): teller = trigger.nick verb, tellee, msg = trigger.groups() verb = unicode(verb) tellee = Nick(tellee.rstrip('.,:;')) msg = unicode(msg) if not os.path.exists(willie.tell_filename): return if len(tellee) > 20: return willie.reply('That nickname is too long.') if tellee == willie.nick: return willie.reply("I'm here now, you can tell me whatever you want!") tz, tformat = get_user_time(willie, tellee) print tellee, tz, tformat timenow = datetime.datetime.now(tz).strftime(tformat) if not tellee in (Nick(teller), willie.nick, 'me'): willie.memory['tell_lock'].acquire() try: if not willie.memory['reminders'].has_key(tellee): willie.memory['reminders'][tellee] = [(teller, verb, timenow, msg)] else: willie.memory['reminders'][tellee].append( (teller, verb, timenow, msg)) finally: willie.memory['tell_lock'].release() response = "I'll pass that on when %s is around." % tellee willie.reply(response) elif Nick(teller) == tellee: willie.say('You can %s yourself that.' % verb) else: willie.say("Hey, I'm not as stupid as Monty you know!") dumpReminders(willie.tell_filename, willie.memory['reminders'], willie.memory['tell_lock']) # @@ tell
def writeNickchangeMessage(trigger): nick1 = Nick(trigger.nick) nick2 = trigger.sender event = trigger.event host = trigger.hostmask message = prepareMessage("%s %s %s %s" % (nick1, event, nick2, host)) nick1fn = conf.get('main', 'basedir') + conf.get('main', 'nicksdir') + \ nick1 + '/events' nick2fn = conf.get('main', 'basedir') + conf.get('main', 'nicksdir') + \ nick2 + '/events' writeLogFile(nick1fn, message) writeLogFile(nick2fn, message)
def writeEventMessage(trigger): # writes join/part/quit messages nick = Nick(trigger.nick) event = trigger.event channel = trigger.sender host = trigger.hostmask if event == 'QUIT': message = prepareMessage("%s %s" % (event, host)) else: message = prepareMessage("%s %s %s" % (event, channel, host)) fn = conf.get('main', 'basedir') + conf.get('main', 'nicksdir') + \ nick + '/events' writeLogFile(fn, message)
def track_kick(bot, trigger): nick = Nick(trigger.args[1]) if nick == bot.nick: bot.channels.remove(trigger.sender) del bot.privileges[trigger.sender] else: # Temporary fix to stop KeyErrors from being sent to channel # The privileges dict may not have all nicks stored at all times # causing KeyErrors try: del bot.privileges[trigger.sender][nick] except KeyError: pass
def f_remind(bot, trigger): """Give someone a message the next time they're seen""" teller = trigger.nick verb = trigger.group(1) tellee, msg = trigger.group(2).split(None, 1) tellee = Nick(tellee.rstrip(".,:;")) if not os.path.exists(bot.tell_filename): return if len(tellee) > 20: return bot.reply("That nickname is too long.") if tellee == bot.nick: return bot.reply("I'm here now, you can tell me whatever you want!") tz, tformat = get_user_time(bot, tellee) print tellee, tz, tformat timenow = datetime.datetime.now(tz).strftime(tformat) if not tellee in (Nick(teller), bot.nick, "me"): bot.memory["tell_lock"].acquire() try: if not tellee in bot.memory["reminders"]: bot.memory["reminders"][tellee] = [(teller, verb, timenow, msg)] else: bot.memory["reminders"][tellee].append((teller, verb, timenow, msg)) finally: bot.memory["tell_lock"].release() response = "I'll pass that on when %s is around." % tellee bot.reply(response) elif Nick(teller) == tellee: bot.say("You can %s yourself that." % verb) else: bot.say("Hey, I'm not as stupid as Monty you know!") dumpReminders(bot.tell_filename, bot.memory["reminders"], bot.memory["tell_lock"]) # @@ tell
def f_remind(willie, trigger): teller = trigger.nick verb, tellee, msg = trigger.groups() verb = unicode(verb) tellee = Nick(tellee.rstrip(".,:;")) msg = unicode(msg) if not os.path.exists(willie.tell_filename): return if len(tellee) > 20: return willie.reply("That nickname is too long.") if tellee == willie.nick: return willie.reply("I'm here now, you can tell me whatever you want!") tz, tformat = get_user_time(willie, tellee) print tellee, tz, tformat timenow = datetime.datetime.now(tz).strftime(tformat) if not tellee in (Nick(teller), willie.nick, "me"): willie.memory["tell_lock"].acquire() try: if not willie.memory["reminders"].has_key(tellee): willie.memory["reminders"][tellee] = [(teller, verb, timenow, msg)] else: willie.memory["reminders"][tellee].append((teller, verb, timenow, msg)) finally: willie.memory["tell_lock"].release() response = "I'll pass that on when %s is around." % tellee willie.reply(response) elif Nick(teller) == tellee: willie.say("You can %s yourself that." % verb) else: willie.say("Hey, I'm not as stupid as Monty you know!") dumpReminders(willie.tell_filename, willie.memory["reminders"], willie.memory["tell_lock"]) # @@ tell
def kick(bot, trigger): """ Kick a user from the channel. """ if (not trigger.owner) and (not trigger.admin) and (bot.privileges[trigger.sender][trigger.nick] < OP): return text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) nick = opt channel = trigger.sender reasonidx = 2 if not opt.is_nick(): if argc < 3: return nick = text[2] channel = opt reasonidx = 3 reason = ' '.join(text[reasonidx:]) if nick != bot.config.nick: bot.write(['KICK', channel, nick, reason])
def quiet(bot, trigger): """ This gives admins the ability to quiet a user. The bot must be a Channel Operator for this command to work """ if (not trigger.owner) and (not trigger.admin) and (bot.privileges[trigger.sender][trigger.nick] < OP): return text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) quietmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return quietmask = text[2] channel = opt quietmask = configureHostMask(quietmask) if quietmask == '': return bot.write(['MODE', channel, '+q', quietmask])
def unban(bot, trigger): """ Remueve un veto en el canal """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < HALFOP: return bot.reply("No soy un operador de este canal!") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) banmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return channel = opt banmask = text[2] banmask = configureHostMask(banmask) if banmask == '': return bot.write(['MODE', channel, '-b', banmask])
def unquiet(bot, trigger): """ Quita el silencio de un usuario o máscara """ if bot.privileges[trigger.sender][trigger.nick] < OP: return if bot.privileges[trigger.sender][bot.nick] < OP: return bot.reply("No soy operador de este canal!!") text = trigger.group().split() argc = len(text) if argc < 2: return opt = Nick(text[1]) quietmask = opt channel = trigger.sender if not opt.is_nick(): if argc < 3: return quietmask = text[2] channel = opt quietmask = configureHostMask(quietmask) if quietmask == '': return bot.write(['MODE', opt, '-q', quietmask])
def f_optin_check(willie, trigger): """ check to see if i've opted in. """ if not willie.db: return nick = Nick(trigger.nick) if optin_check(willie, nick): willie.say('{nick}: You opted in to auto-tweet links on {date}'.format( nick=nick, date=willie.db.preferences.get(nick, 'optin_auto_tweet_date'))) else: willie.say( '{nick}: Does not appear you have optin in to auto-tweet links.'. format(nick=nick))
def seen(bot, trigger): """Reports when and where the user was last seen.""" if not trigger.group(2): bot.say(".seen <nick> - Reports when <nick> was last seen.") return nick = Nick(trigger.group(2).strip()) if nick in seen_dict: timestamp = seen_dict[nick]['timestamp'] channel = seen_dict[nick]['channel'] message = seen_dict[nick]['message'] tz, tformat = get_user_time(bot, trigger.nick) saw = datetime.datetime.fromtimestamp(timestamp, tz) timestamp = saw.strftime(tformat) msg = "I last saw %s at %s on %s, saying %s" % (nick, timestamp, channel, message) bot.say(str(trigger.nick) + ': ' + msg) else: bot.say("Sorry, I haven't seen %s around." % nick)
def take_comment(bot, trigger): """ Log a comment, to be shown with other comments when a chair uses .comments. Intended to allow commentary from those outside the primary group of people in the meeting. Used in private message only, as `.comment <#channel> <comment to add>` https://github.com/embolalia/willie/wiki/Using-the-meetbot-module """ target, message = trigger.group(2).split(None, 1) target = Nick(target) if not trigger.sender.is_nick(): return if not ismeetingrunning(target): bot.say("There's not currently a meeting in that channel.") else: meetings_dict[trigger.group(3)]['comments'].append((trigger.nick, message)) bot.say("Your comment has been recorded. It will be shown when the" " chairs tell me to show the comments.") bot.msg(meetings_dict[trigger.group(3)]['head'], "A new comment has been recorded.")