def test_channel_has_privilege(): channel = target.Channel(Identifier('#chan')) user = target.User(Identifier('TestUser'), 'example', 'example.com') # unknown user assert not channel.has_privilege(user.nick, plugin.VOICE) assert not channel.has_privilege(user.nick, plugin.OP) # user added without privileges channel.add_user(user) assert not channel.has_privilege(user.nick, plugin.VOICE) assert not channel.has_privilege(user.nick, plugin.OP) # user added with VOICE privilege channel.add_user(user, plugin.VOICE) assert channel.has_privilege(user.nick, plugin.VOICE) assert not channel.has_privilege(user.nick, plugin.OP) # user added with OP privilege channel.add_user(user, plugin.OP) assert channel.has_privilege(user.nick, plugin.VOICE) assert channel.has_privilege(user.nick, plugin.OP) # user added with both VOICE & OP privilege channel.add_user(user, plugin.VOICE | plugin.OP) assert channel.has_privilege(user.nick, plugin.VOICE) assert channel.has_privilege(user.nick, plugin.OP)
def track_notify(bot, trigger): """Track users going away or coming back.""" if trigger.nick not in bot.users: bot.users[trigger.nick] = target.User(trigger.nick, trigger.user, trigger.host) user = bot.users[trigger.nick] user.away = bool(trigger.args)
def track_join(bot, trigger): channel = trigger.sender # is it a new channel? if channel not in bot.channels: LOGGER.info('Channel joined: %s', channel) bot.privileges[channel] = dict() bot.channels[channel] = target.Channel(channel) # did *we* just join? if trigger.nick == bot.nick: if bot.settings.core.throttle_join: LOGGER.debug('JOIN event added to queue for channel: %s', channel) bot.memory['join_events_queue'].append(channel) else: LOGGER.debug('Send direct WHO for channel: %s', channel) _send_who(bot, channel) # set initial values bot.privileges[channel][trigger.nick] = 0 user = bot.users.get(trigger.nick) if user is None: user = target.User(trigger.nick, trigger.user, trigger.host) bot.users[trigger.nick] = user bot.channels[channel].add_user(user) if len(trigger.args) > 1 and trigger.args[1] != '*' and ( 'account-notify' in bot.enabled_capabilities and 'extended-join' in bot.enabled_capabilities): user.account = trigger.args[1]
def account_notify(bot, trigger): if trigger.nick not in bot.users: bot.users[trigger.nick] = target.User(trigger.nick, trigger.user, trigger.host) account = trigger.args[0] if account == '*': account = None bot.users[trigger.nick].account = account
def track_notify(bot, trigger): """Track users going away or coming back.""" if trigger.nick not in bot.users: bot.users[trigger.nick] = target.User(trigger.nick, trigger.user, trigger.host) user = bot.users[trigger.nick] user.away = bool(trigger.args) state_change = 'went away' if user.away else 'came back' LOGGER.info("User %s: %s", state_change, trigger.nick)
def test_channel_is_priv_level_unknown_user(): channel = target.Channel(Identifier('#chan')) user = target.User(Identifier('TestUser'), 'example', 'example.com') assert not channel.is_oper(user.nick) assert not channel.is_owner(user.nick) assert not channel.is_admin(user.nick) assert not channel.is_op(user.nick) assert not channel.is_halfop(user.nick) assert not channel.is_voiced(user.nick)
def account_notify(bot, trigger): """Track users' accounts.""" if trigger.nick not in bot.users: bot.users[trigger.nick] = target.User(trigger.nick, trigger.user, trigger.host) account = trigger.args[0] if account == '*': account = None bot.users[trigger.nick].account = account LOGGER.info("Update account for nick %r: %s", trigger.nick, account)
def test_channel_add_user_voiced(): channel = target.Channel(Identifier('#chan')) user = target.User(Identifier('TestUser'), 'example', 'example.com') channel.add_user(user, plugin.VOICE) assert user.nick in channel.users assert channel.users[user.nick] is user assert user.nick in channel.privileges assert channel.privileges[user.nick] == plugin.VOICE
def handle_names(bot, trigger): """Handle NAMES responses. This function keeps track of users' privileges when Sopel joins channels. """ # TODO specific to one channel type. See issue 281. channels = re.search(r'(#\S*)', trigger.raw) if not channels: return channel = Identifier(channels.group(1)) if channel not in bot.channels: bot.channels[channel] = target.Channel(channel) # This could probably be made flexible in the future, but I don't think # it'd be worth it. # If this ever needs to be updated, remember to change the mode handling in # the WHO-handler functions below, too. mapping = { "+": plugin.VOICE, "%": plugin.HALFOP, "@": plugin.OP, "&": plugin.ADMIN, "~": plugin.OWNER, "!": plugin.OPER, } uhnames = 'UHNAMES' in bot.isupport userhost_in_names = 'userhost-in-names' in bot.enabled_capabilities names = trigger.split() for name in names: if uhnames or userhost_in_names: name, mask = name.rsplit('!', 1) username, hostname = mask.split('@', 1) else: username = hostname = None priv = 0 for prefix, value in mapping.items(): if prefix in name: priv = priv | value nick = Identifier(name.lstrip(''.join(mapping.keys()))) user = bot.users.get(nick) if user is None: # The username/hostname will be included in a NAMES reply only if # userhost-in-names is available. We can use them if present. # Fortunately, the user should already exist in bot.users by the # time this code runs, so this is 99.9% ass-covering. user = target.User(nick, username, hostname) bot.users[nick] = user bot.channels[channel].add_user(user, privs=priv)
def test_channel_add_user(): channel = target.Channel(Identifier('#chan')) user = target.User(Identifier('TestUser'), 'example', 'example.com') channel.add_user(user) assert user.nick in channel.users assert channel.users[user.nick] is user assert user.nick in channel.privileges assert channel.privileges[user.nick] == 0 assert channel.name in user.channels
def test_channel_add_user_replace(): channel = target.Channel(Identifier('#chan')) user = target.User(Identifier('TestUser'), 'example', 'example.com') channel.add_user(user, plugin.VOICE) channel.add_user(user, plugin.OP) assert user.nick in channel.users assert channel.users[user.nick] is user assert user.nick in channel.privileges assert channel.privileges[user.nick] == plugin.OP assert channel.privileges[user.nick] & plugin.VOICE == 0, ( 'This user must be replaced, without previous privileges')
def handle_names(bot, trigger): """Handle NAMES responses. This function keeps track of users' privileges when Sopel joins channels. """ names = trigger.split() # TODO specific to one channel type. See issue 281. channels = re.search(r'(#\S*)', trigger.raw) if not channels: return channel = Identifier(channels.group(1)) if channel not in bot.privileges: bot.privileges[channel] = {} if channel not in bot.channels: bot.channels[channel] = target.Channel(channel) # This could probably be made flexible in the future, but I don't think # it'd be worth it. # If this ever needs to be updated, remember to change the mode handling in # the WHO-handler functions below, too. mapping = { "+": module.VOICE, "%": module.HALFOP, "@": module.OP, "&": module.ADMIN, "~": module.OWNER, "!": module.OPER, } for name in names: priv = 0 for prefix, value in iteritems(mapping): if prefix in name: priv = priv | value nick = Identifier(name.lstrip(''.join(mapping.keys()))) bot.privileges[channel][nick] = priv user = bot.users.get(nick) if user is None: # It's not possible to set the username/hostname from info received # in a NAMES reply, unfortunately. # Fortunately, the user should already exist in bot.users by the # time this code runs, so this is 99.9% ass-covering. user = target.User(nick, None, None) bot.users[nick] = user bot.channels[channel].add_user(user, privs=priv)
def recv_chghost(bot, trigger): """Track user/host changes.""" if trigger.nick not in bot.users: bot.users[trigger.nick] = target.User(trigger.nick, trigger.user, trigger.host) try: new_user, new_host = trigger.args except ValueError: LOGGER.warning("Ignoring CHGHOST command with %s arguments: %r", 'extra' if len(trigger.args) > 2 else 'insufficient', trigger.args) return bot.users[trigger.nick].user = new_user bot.users[trigger.nick].host = new_host LOGGER.info("Update user@host for nick %r: %s@%s", trigger.nick, new_user, new_host)
def _record_who(bot, channel, user, host, nick, account=None, away=None, modes=None): nick = Identifier(nick) channel = Identifier(channel) if nick not in bot.users: usr = target.User(nick, user, host) bot.users[nick] = usr else: usr = bot.users[nick] # check for & fill in sparse User added by handle_names() if usr.host is None and host: usr.host = host if usr.user is None and user: usr.user = user if account == '0': usr.account = None else: usr.account = account if away is not None: usr.away = away priv = 0 if modes: mapping = { "+": module.VOICE, "%": module.HALFOP, "@": module.OP, "&": module.ADMIN, "~": module.OWNER, "!": module.OPER, } for c in modes: priv = priv | mapping[c] if channel not in bot.channels: bot.channels[channel] = target.Channel(channel) bot.channels[channel].add_user(usr, privs=priv) if channel not in bot.privileges: bot.privileges[channel] = {} bot.privileges[channel][nick] = priv
def track_join(bot, trigger): """Track users joining channels. When a user joins a channel, the bot will send (or queue) a ``WHO`` command to know more about said user (privileges, modes, etc.). """ channel = trigger.sender # is it a new channel? if channel not in bot.channels: bot.privileges[channel] = {} bot.channels[channel] = target.Channel(channel) # did *we* just join? if trigger.nick == bot.nick: LOGGER.info("Channel joined: %s", channel) if bot.settings.core.throttle_join: LOGGER.debug("JOIN event added to queue for channel: %s", channel) bot.memory['join_events_queue'].append(channel) else: LOGGER.debug("Send MODE and direct WHO for channel: %s", channel) bot.write(["MODE", channel]) _send_who(bot, channel) else: LOGGER.info("Channel %r joined by user: %s", str(channel), trigger.nick) # set initial values bot.privileges[channel][trigger.nick] = 0 user = bot.users.get(trigger.nick) if user is None: user = target.User(trigger.nick, trigger.user, trigger.host) bot.users[trigger.nick] = user bot.channels[channel].add_user(user) if len(trigger.args) > 1 and trigger.args[1] != '*' and ( 'account-notify' in bot.enabled_capabilities and 'extended-join' in bot.enabled_capabilities): user.account = trigger.args[1]
def track_notify(bot, trigger): if trigger.nick not in bot.users: bot.users[trigger.nick] = target.User(trigger.nick, trigger.user, trigger.host) user = bot.users[trigger.nick] user.away = bool(trigger.args)