def topic_details(self, _, line): """Show the details of a topic.""" channel = line.params[1] setter = self.nick_colour(Hostmask.parse(line.params[2]).nick) set_on = str(datetime.utcfromtimestamp(int(line.params[3]))) self._printf("*** Topic of {} set by {} on {}.".format(channel, setter, set_on))
def topic_details(self, _, line): """Show the details of a topic.""" channel = line.params[1] setter = self.nick_colour(Hostmask.parse(line.params[2]).nick) set_on = str(datetime.utcfromtimestamp(int(line.params[3]))) self._printf("*** Topic of {} set by {} on {}.".format( channel, setter, set_on))
def topic_who_time(self, _, line): """Update the channel's topic metadata.""" channel = self.get_channel(line.params[1]) if channel is None: _logger.debug("Topic time for unknown channel: %s", line.params[1]) return channel.topicwho = Hostmask.parse(line.params[2]) channel.topictime = int(line.params[3])
def kick(self, _, line): """Fire a (scope, user_kick) event for users being kicked.""" params = line.params channel = params[0] target = Hostmask(nick=params[1]) reason = params[2] scope = Scope(target, channel, True, reason=reason, cause=line.hostmask) self.call_event("scope", "user_kick", scope)
def prefix(self, _, setter, target, mode): # Parse into hostmask in case of usernames-in-host channel = self.get_channel(target) if channel is None: _logger.warning("Got a PREFIX event for an unknown channel: %s", target) return hostmask = Hostmask.parse(mode.param) if mode.adding: channel.users[hostmask.nick].add(mode.mode) else: channel.users[hostmask.nick].discard(mode.mode)
def monitor_offline(self, _, line): """Remove users who go offline on MONITOR.""" if not self._usable: return monitor = [Hostmask.parse(h) for h in line.params[-1].split(",")] if not monitor: return user_track = self.base.user_track for user in monitor: if user_track.get_user(user.nick): user_track.remove_user(user.nick)
def monitor_online(self, _, line): """Add users who come online on MONITOR.""" if not self._usable: return monitor = [Hostmask.parse(h) for h in line.params[-1].split(",")] if not monitor: return user_track = self.base.user_track for user in monitor: user_track.add_user(user.nick, username=user.username, host=user.host)
def test_channel_topic_user(self): """Ensure topic set by user is handled correctly.""" name = '#Sporks' topic = "#Sporks - we'll bring yo dick" setter = Hostmask(nick='lstarnes', username='******', host='interlinked/netadmin/automaton/lstarnes') set_on = int(time()) # 1437288043 irc = self.connection irc.inject_line(join_line(irc, name)) irc.inject_line( Line(hostmask=setter, command='TOPIC', params=(name, topic))) self.assertTopicEqual(topic, setter, set_on)
def parse_stats_opers(self, _, line): """Evaluate a stats line for an oper.""" if line.params[1] != 'p': return match = _charybdis_oper_re.match(line.params[-1]) if not match: return nick = match.group("nick") user = match.group("user") host = match.group("host") hostmask = Hostmask(nick=nick, user=user, host=host) entry = OperEntry(None, None, hostmask, None) return self.call_event("stats", "oper", entry)
def prefix(self, event): # Parse into hostmask in case of usernames-in-host hostmask = Hostmask.parse(event.param) assert hostmask user = self.get_user(hostmask.nick) if not user: # Add the user user = self.add_user(hostmask.nick, user=hostmask.username, host=hostmask.host) channel = user.channels[event.target] if event.adding: channel.add(event.mode) else: channel.discard(event.mode)
def test_channel_topic_server_server(self): """Ensure topic sent from and set by server is handled correctly.""" name = '#help' topic = 'Official help channel | To register a nick : /msg NickServ '\ 'help register | To group a nick, /msg nickserv help group | '\ 'Lost password? /msg nickserv SENDPASS <accountname> | State '\ 'your question and people will answer eventually (It might '\ 'take 10 or so minutes)' setter = 'chrysalis.server' set_on = 1395559296 irc = self.connection irc.inject_line(join_line(irc, name)) irc.inject_line(rpl_topic_line(irc, name, topic)) irc.inject_line(rpl_topiwhotime_line(irc, name, setter, set_on)) self.assertTopicEqual(topic, Hostmask(host=setter), set_on)
def userhost_parse(mask): """Parse a USERHOST reply. :returns: An object with the following attributes set: :hostmask: :py:class:`~PyIRC.line.Hostmask` of the user. This may be a cloak. :operator: Whether or not the user is an operator. False does not mean they are not an operator, as operators may be hidden on the server. :away: Whether or not the user is away. """ if not mask: raise ValueError("Need a mask to parse") ret = SimpleNamespace(hostmask=None, operator=None, away=None) nick, sep, userhost = mask.partition('=') if not sep: return ret if nick.endswith('*'): nick = nick[:-1] ret.operator = True if userhost.startswith(('+', '-')): away, userhost = userhost[0], userhost[:1] ret.away = (away == '+') # user@host username, sep, host = userhost.partition('@') if not sep: host = username username = None ret.hostmask = Hostmask(nick=nick, username=username, host=host) return ret
def test_channel_topic_server_user(self): """Ensure topic sent from server, set by user, is handled correctly.""" name = '#gentoo-python' topic = 'Set e.g. PYTHON_TARGETS="python2_7 python3_2 python3_3 '\ 'python3_4" in /etc/make.conf if you want to install Python '\ 'modules for multiple Python versions. | '\ 'http://www.gentoo.org/proj/en/Python/#doc_chap5' setter = Hostmask(nick='xiaomiao', username='******', host='gentoo/developer/bonsaikitten') set_on = 1404711155 irc = self.connection irc.inject_line(join_line(irc, name)) irc.inject_line(rpl_topic_line(irc, name, topic)) irc.inject_line(rpl_topiwhotime_line(irc, name, setter, set_on)) self.assertTopicEqual(topic, setter, set_on)
def prefix(self, _, setter, target, mode): """Update the channel mode of a user.""" # pylint: disable=unused-argument # Parse into hostmask in case of usernames-in-host hostmask = Hostmask.parse(mode.param) assert hostmask user = self.get_user(hostmask.nick) if user is None: # This can happen from override or ChanServ guard off user = self.add_user(hostmask.nick, username=hostmask.username, host=hostmask.host) self.timeout_user(hostmask.nick) channel = user.channels[target] if mode.adding: channel.add(mode.mode) else: channel.discard(mode.mode)
def names(self, _, line): """Handle bursting of new users from NAMES.""" params = line.params channel = params[2] isupport = self.base.isupport prefix = prefix_parse(isupport.get("PREFIX")) for hostmask in params[3].split(' '): if not hostmask: continue modes, hostmask = status_prefix_parse(hostmask, prefix) hostmask = Hostmask.parse(hostmask) modes = [(m, hostmask, True, None) for m in modes] scope = Scope( hostmask, channel, False, cause=line.hostmask, modes=modes) self.call_event("scope", "user_burst", scope)
def parse_stats_opers(self, _, line): """Evaluate a stats line for an oper.""" if line.params[1] != 'p': return match = _hybrid_oper_re(line.params[-1]) if not match: return flag = match.group("flag") privs = match.group("privs") nick = match.group("nick") user = match.group("user") host = match.group("host") hostmask = Hostmask(nick=nick, user=user, host=host) idle = int(match.group("idle")) entry = OperEntry(flag, privs, hostmask, idle) return self.call_event("stats", "oper", entry)
def handle_list(self, caller, line): modechar = self.mode_chars[caller.eventpair[1]] params = line.params try: target = params[1] mask = params[2] if len(params) > 3: setter = Hostmask.parse(params[3]) if len(params) > 4: timestamp = int(params[4]) else: setter = line.hostmask timestamp = None except Exception as e: _logger.warning("Bogus list mode received: %s (exception: %s)", modechar, e) return mode = Mode(modechar, mask, True, timestamp) self.call_event("modes", "mode_list", setter, target, mode)
def handle_list(self, event, mode): line = event.line params = line.params try: target = params[1] mask = params[2] if len(params) > 3: setter = Hostmask.parse(params[3]) if len(params) > 4: timestamp = int(params[4]) else: setter = line.hostmask timestamp = None except Exception as e: logger.warning("Bogus list mode received: %s (exception: %s)", mode, e) return self.call_event("modes", "mode_list", line, setter, target, True, mode, mask, timestamp)
def banmask_parse(string, supported_extban): """Normalise a ban mask into either an extban or nick!user@host set""" ret = SimpleNamespace() ret.nick = ret.user = ret.host = None extban = extban_parse(string, supported_extban) if extban: # Unpack ret.extban, ret.extban_target = extban return ret ret.extban = ret.extban_target = None try: hostmask = Hostmask.parse(string) except Exception: return ret if not hostmask: return ret ret.nick, ret.user, ret.host = hostmask.nick, hostmask.user, hostmask.host return ret
def _parse_ban_lines(line): """Parse a foo:line in Hybrid-derived servers, excluding RESV and X:lines.""" params = line.params match = _stats_ban_re.match(params[-1]) assert match, "Bug in the stats matching regex!" t = match.group("type") if t == "K" or t == "G": # Don't use Hostmask, because this is for matching purposes. mask = (params[3], params[4], params[2]) elif t == "D": mask = params[2] else: _logger.warning("Unknown bantype, just guessing!") mask = params[:-1] duration = int(match.group("duration")) * 60 year = int(match.group("year")) month = int(match.group("month")) day = int(match.group("day")) hour = int(match.group("hour")) minute = int(match.group("minute")) if all(x is not None for x in (year, month, day)): setdate = datetime(year, month, day, hour, minute) else: setdate = None reason = match.group("reason") oreason = match.group("oreason") settermask = Hostmask.parse(match.group("settermask")) setter = match.group("setter") return BanEntry(mask, settermask, setter, setdate, duration, reason, oreason)
def banmask_parse(string, supported_extban): """Normalise a ban mask into either an extban or nick!user@host set.""" ret = SimpleNamespace() ret.nick = ret.user = ret.host = None extban = extban_parse(string, supported_extban) if extban: # Unpack ret.extban, ret.extban_target = extban return ret ret.extban = ret.extban_target = None try: hostmask = Hostmask.parse(string) except ValueError: return ret if not hostmask: return ret ret.nick, ret.user, ret.host = (hostmask.nick, hostmask.username, hostmask.host) return ret
def conn_mask(connection): return Hostmask(nick=connection.nick, username=connection.username, host='test-connection.local')