From a1e1922e62419de75d2909dfae1ee7caa9ed487f Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 16 May 2020 22:08:40 -0400 Subject: Add xmldocs, and handle null bytes --- IRCStates/Channel.cs | 10 +- IRCStates/ChannelUser.cs | 7 +- IRCStates/Extensions.cs | 7 + IRCStates/IRCStates.csproj | 1 + IRCStates/ISupport.cs | 32 ++-- IRCStates/ISupportChanModes.cs | 12 +- IRCStates/ISupportPrefix.cs | 9 +- IRCStates/Numeric.cs | 3 + IRCStates/Server.cs | 399 +++++++++++++++++++++++++++++++---------- IRCStates/User.cs | 6 +- 10 files changed, 364 insertions(+), 122 deletions(-) (limited to 'IRCStates') diff --git a/IRCStates/Channel.cs b/IRCStates/Channel.cs index 60ca3fb..a9d2302 100644 --- a/IRCStates/Channel.cs +++ b/IRCStates/Channel.cs @@ -13,15 +13,15 @@ namespace IRCStates Modes = new Dictionary(); } - public string Name { get; set; } - public string NameLower { get; set; } - public Dictionary Users { get; set; } + public string Name { get; private set; } + public string NameLower { get; private set; } + public Dictionary Users { get; private set; } public string Topic { get; set; } public string TopicSetter { get; set; } public DateTime TopicTime { get; set; } public DateTime Created { get; set; } - public Dictionary> ListModes { get; set; } - public Dictionary Modes { get; set; } + public Dictionary> ListModes { get; private set; } + public Dictionary Modes { get; private set; } public override string ToString() { diff --git a/IRCStates/ChannelUser.cs b/IRCStates/ChannelUser.cs index 8c2298b..bc5e99b 100644 --- a/IRCStates/ChannelUser.cs +++ b/IRCStates/ChannelUser.cs @@ -9,9 +9,9 @@ namespace IRCStates Modes = new List(); } - public List Modes { get; set; } + public List Modes { get; } - protected bool Equals(ChannelUser other) + private bool Equals(ChannelUser other) { return other != null && Equals(Modes, other.Modes); } @@ -20,8 +20,7 @@ namespace IRCStates { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((ChannelUser) obj); + return obj.GetType() == GetType() && Equals((ChannelUser) obj); } public override int GetHashCode() diff --git a/IRCStates/Extensions.cs b/IRCStates/Extensions.cs index c807dbb..6cce3d4 100644 --- a/IRCStates/Extensions.cs +++ b/IRCStates/Extensions.cs @@ -5,6 +5,13 @@ namespace IRCStates { public static class Extensions { + /// + /// Update the dictionary with 's keys and values + /// + /// + /// + /// + /// public static void UpdateWith(this Dictionary dict, Dictionary other) { if (dict == null || other == null || !other.Any()) return; diff --git a/IRCStates/IRCStates.csproj b/IRCStates/IRCStates.csproj index 76c4bf4..162f592 100644 --- a/IRCStates/IRCStates.csproj +++ b/IRCStates/IRCStates.csproj @@ -13,6 +13,7 @@ https://tildegit.org/ben/ircsharp/src/branch/master/IRCStates git irc + 1.0.1 diff --git a/IRCStates/ISupport.cs b/IRCStates/ISupport.cs index b8a5651..8dfcb0c 100644 --- a/IRCStates/ISupport.cs +++ b/IRCStates/ISupport.cs @@ -21,21 +21,25 @@ namespace IRCStates Whox = false; } - public Dictionary Raw { get; set; } - public string Network { get; set; } - public ISupportChanModes ChanModes { get; set; } - public ISupportPrefix Prefix { get; set; } - public int? Modes { get; set; } - public Casemap.CaseMapping CaseMapping { get; set; } - public List ChanTypes { get; set; } - public List StatusMsg { get; set; } - public string CallerId { get; set; } - public string Excepts { get; set; } - public string Invex { get; set; } - public int? Monitor { get; set; } - public int? Watch { get; set; } - public bool Whox { get; set; } + public Dictionary Raw { get; } + public string Network { get; private set; } + public ISupportChanModes ChanModes { get; private set; } + public ISupportPrefix Prefix { get; private set; } + public int? Modes { get; private set; } + public Casemap.CaseMapping CaseMapping { get; private set; } + public List ChanTypes { get; private set; } + public List StatusMsg { get; private set; } + public string CallerId { get; private set; } + public string Excepts { get; private set; } + public string Invex { get; private set; } + public int? Monitor { get; private set; } + public int? Watch { get; private set; } + public bool Whox { get; private set; } + /// + /// Parse the ISupport values from the line's parameters + /// + /// public void Parse(IEnumerable tokens) { if (tokens == null) return; diff --git a/IRCStates/ISupportChanModes.cs b/IRCStates/ISupportChanModes.cs index e63c15f..5a175da 100644 --- a/IRCStates/ISupportChanModes.cs +++ b/IRCStates/ISupportChanModes.cs @@ -6,6 +6,10 @@ namespace IRCStates { public class ISupportChanModes { + /// + /// Split the chanmodes and add to our known + /// + /// public ISupportChanModes(string splitVal) { if (splitVal == null) return; @@ -25,9 +29,9 @@ namespace IRCStates SettingDModes.AddRange(split[3].Select(c => c.ToString(CultureInfo.InvariantCulture))); } - public List ListModes { get; set; } - public List SettingBModes { get; set; } - public List SettingCModes { get; set; } - public List SettingDModes { get; set; } + public List ListModes { get; } + public List SettingBModes { get; } + public List SettingCModes { get; } + public List SettingDModes { get; } } } diff --git a/IRCStates/ISupportPrefix.cs b/IRCStates/ISupportPrefix.cs index 35c5344..146bdcc 100644 --- a/IRCStates/ISupportPrefix.cs +++ b/IRCStates/ISupportPrefix.cs @@ -7,6 +7,11 @@ namespace IRCStates { public class ISupportPrefix { + /// + /// Split the prefix value and add them to our known and + /// + /// + /// public ISupportPrefix(string splitVal) { if (splitVal == null) throw new ArgumentNullException(nameof(splitVal)); @@ -18,8 +23,8 @@ namespace IRCStates Prefixes.AddRange(split[1].Select(c => c.ToString(CultureInfo.InvariantCulture))); } - public List Modes { get; set; } - public List Prefixes { get; set; } + public List Modes { get; } + public List Prefixes { get; } public string FromMode(char mode) { diff --git a/IRCStates/Numeric.cs b/IRCStates/Numeric.cs index 1ccbd76..674e313 100644 --- a/IRCStates/Numeric.cs +++ b/IRCStates/Numeric.cs @@ -2,6 +2,9 @@ namespace IRCStates { + /// + /// Known numeric response codes + /// public static class Numeric { #pragma warning disable CA1707 // Identifiers should not contain underscores diff --git a/IRCStates/Server.cs b/IRCStates/Server.cs index b4a0145..2cbbb92 100644 --- a/IRCStates/Server.cs +++ b/IRCStates/Server.cs @@ -11,7 +11,7 @@ namespace IRCStates public const string WhoType = "525"; // randomly generated private readonly StatefulDecoder _decoder; - private readonly Dictionary TempCaps; + private readonly Dictionary _tempCaps; public Server(string name) { @@ -24,7 +24,7 @@ namespace IRCStates Channels = new Dictionary(); ISupport = new ISupport(); HasCap = false; - TempCaps = new Dictionary(); + _tempCaps = new Dictionary(); AvailableCaps = new Dictionary(); AgreedCaps = new List(); } @@ -54,56 +54,107 @@ namespace IRCStates return $"Server(name={Name})"; } + /// + /// Use 's case mapping to convert to lowercase + /// + /// + /// public string CaseFold(string str) { return Casemap.CaseFold(ISupport.CaseMapping, str); } - private bool CaseFoldEquals(string s1, string s2) - { - return CaseFold(s1) == CaseFold(s2); - } - + /// + /// Is the current nickname this client? + /// + /// + /// private bool IsMe(string nickname) { return CaseFold(nickname) == NickNameLower; } + /// + /// Check for a user - not case sensitive + /// + /// + /// private bool HasUser(string nickname) { return Users.ContainsKey(CaseFold(nickname)); } - private User AddUser(string nickname, string nicknameLower) + /// + /// Get existing user by case-insensitive nickname + /// + /// + /// + private User GetUser(string nickname) { - var user = CreateUser(nickname, nicknameLower); - Users[nicknameLower] = user; + return HasUser(nickname) ? Users[CaseFold(nickname)] : null; + } + + /// + /// Create and add user + /// + /// + /// + private User AddUser(string nickname) + { + var user = CreateUser(nickname); + Users[CaseFold(nickname)] = user; return user; } - private User CreateUser(string nickname, string nicknameLower) + /// + /// Build a new and update correct case-mapped nick + /// + /// + /// + private User CreateUser(string nickname) { var user = new User(); - user.SetNickName(nickname, nicknameLower); + user.SetNickName(nickname, CaseFold(nickname)); return user; } + /// + /// Is the channel a valid ISupport type? + /// + /// + /// private bool IsChannel(string target) { return !string.IsNullOrEmpty(target) && ISupport.ChanTypes.Contains(target[0].ToString(CultureInfo.InvariantCulture)); } + /// + /// Is the channel known to this client? + /// + /// + /// public bool HasChannel(string name) { - return Channels.ContainsKey(CaseFold(name)); + return IsChannel(name) && Channels.ContainsKey(CaseFold(name)); } + /// + /// Get the channel if it's known to us + /// + /// + /// private Channel GetChannel(string name) { - return HasChannel(name) ? Channels[name] : null; + return HasChannel(name) ? Channels[CaseFold(name)] : null; } + /// + /// Add a to a + /// + /// + /// + /// the that was added private ChannelUser UserJoin(Channel channel, User user) { var channelUser = new ChannelUser(); @@ -112,6 +163,11 @@ namespace IRCStates return channelUser; } + /// + /// Set own , , and + /// from a given + /// + /// private void SelfHostmask(Hostmask hostmask) { NickName = hostmask.NickName; @@ -119,6 +175,19 @@ namespace IRCStates if (hostmask.HostName != null) HostName = hostmask.HostName; } + private void SelfHostmask(string raw) + { + SelfHostmask(new Hostmask(raw)); + } + + /// + /// Remove a user from a channel. Used to handle PART and KICK + /// + /// + /// + /// + /// + /// private (Emit, User) UserPart(Line line, string nickName, string channelName, int reasonIndex) { var emit = new Emit(); @@ -128,7 +197,7 @@ namespace IRCStates User user = null; if (HasChannel(channelName)) { - var channel = Channels[channelLower]; + var channel = GetChannel(channelName); emit.Channel = channel; var nickLower = CaseFold(nickName); if (HasUser(nickLower)) @@ -153,6 +222,12 @@ namespace IRCStates return (emit, user); } + /// + /// Update modes on a given modes and parameters + /// + /// + /// + /// private void SetChannelModes(Channel channel, IEnumerable<(bool, string)> modes, IList parameters) { foreach (var (add, c) in modes) @@ -197,6 +272,13 @@ namespace IRCStates } } + /// + /// Handle incoming bytes + /// + /// + /// + /// parsed lines and emits + /// public IEnumerable<(Line, Emit)> Receive(byte[] data, int length) { if (data == null) return null; @@ -204,9 +286,14 @@ namespace IRCStates var lines = _decoder.Push(data, length); if (lines == null) throw new ServerDisconnectedException(); - return lines.Select(l => (l, Parse(l))).ToList(); + return lines.Select(l => (l, Parse(l))); } + /// + /// Delegate a to the correct handler + /// + /// + /// public Emit Parse(Line line) { if (line == null) return null; @@ -256,6 +343,11 @@ namespace IRCStates return emit; } + /// + /// Handles SETNAME command + /// + /// + /// private Emit HandleSetname(Line line) { var emit = new Emit(); @@ -278,6 +370,11 @@ namespace IRCStates return emit; } + /// + /// Handles AWAY command + /// + /// + /// private Emit HandleAway(Line line) { var emit = new Emit(); @@ -300,6 +397,11 @@ namespace IRCStates return emit; } + /// + /// Handles ACCOUNT command + /// + /// + /// private Emit HandleAccount(Line line) { var emit = new Emit(); @@ -322,6 +424,11 @@ namespace IRCStates return emit; } + /// + /// Handles CAP command + /// + /// + /// private Emit HandleCap(Line line) { HasCap = true; @@ -343,11 +450,11 @@ namespace IRCStates switch (subcommand) { case "LS": - TempCaps.UpdateWith(tokens); + _tempCaps.UpdateWith(tokens); if (!multiline) { - AvailableCaps.UpdateWith(TempCaps); - TempCaps.Clear(); + AvailableCaps.UpdateWith(_tempCaps); + _tempCaps.Clear(); } break; @@ -380,6 +487,11 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_LOGGEDIN numeric + /// + /// + /// private Emit HandleLoggedIn(Line line) { SelfHostmask(new Hostmask(line.Params[1])); @@ -387,6 +499,11 @@ namespace IRCStates return new Emit(); } + /// + /// Handles CHGHOST command + /// + /// + /// private Emit HandleChghost(Line line) { var emit = new Emit(); @@ -412,6 +529,11 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_WHOISUSER numeric + /// + /// + /// private Emit HandleWhoIsUser(Line line) { var emit = new Emit(); @@ -440,6 +562,11 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_WHOSPCRPL numeric + /// + /// + /// private Emit HandleWhox(Line line) { var emit = new Emit(); @@ -474,6 +601,11 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_WHOREPLY numeric + /// + /// + /// private Emit HandleWhoReply(Line line) { var emit = new Emit {Target = line.Params[1]}; @@ -502,6 +634,11 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_VISIBLEHOST numeric + /// + /// + /// private Emit HandleVisibleHost(Line line) { var split = line.Params[1].Split('@', 2); @@ -519,22 +656,25 @@ namespace IRCStates return new Emit(); } + /// + /// Handles PRIVMSG, NOTICE, and TAGMSG commands + /// + /// + /// private Emit HandleMessage(Line line) { var emit = new Emit(); var message = line.Params.Count > 1 ? line.Params[1] : null; if (message != null) emit.Text = message; - var nickLower = CaseFold(line.Hostmask.NickName); - if (IsMe(nickLower)) + var nick = CaseFold(line.Hostmask.NickName); + if (IsMe(nick)) { emit.SelfSource = true; SelfHostmask(line.Hostmask); } - var user = HasUser(nickLower) - ? Users[nickLower] - : AddUser(line.Hostmask.NickName, nickLower); + var user = GetUser(nick) ?? AddUser(nick); emit.User = user; if (line.Hostmask.UserName != null) user.UserName = line.Hostmask.UserName; @@ -559,12 +699,17 @@ namespace IRCStates emit.Target = line.Params[0]; if (IsChannel(target) && HasChannel(target)) - emit.Channel = Channels[CaseFold(target)]; + emit.Channel = GetChannel(target); else if (IsMe(target)) emit.SelfTarget = true; return emit; } + /// + /// Handles RPL_UMODEIS numeric + /// + /// + /// private Emit HandleUModeIs(Line line) { foreach (var c in line.Params[1] @@ -576,12 +721,17 @@ namespace IRCStates return new Emit(); } + /// + /// Handles RPL_CHANNELMODEIS numeric + /// + /// + /// private Emit HandleChannelModeIs(Line line) { var emit = new Emit(); if (HasChannel(line.Params[1])) { - var channel = Channels[CaseFold(line.Params[1])]; + var channel = GetChannel(line.Params[1]); emit.Channel = channel; var modes = line.Params[2] .TrimStart('+') @@ -593,6 +743,11 @@ namespace IRCStates return emit; } + /// + /// Handles MODE command + /// + /// + /// private Emit HandleMode(Line line) { var emit = new Emit(); @@ -635,13 +790,17 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_TOPICWHOTIME numeric + /// + /// + /// private Emit HandleTopicTime(Line line) { - var emit = new Emit(); - var channelLower = CaseFold(line.Params[1]); - if (Channels.ContainsKey(channelLower)) + var emit = new Emit(); + if (HasChannel(line.Params[1])) { - var channel = Channels[channelLower]; + var channel = GetChannel(line.Params[1]); emit.Channel = channel; channel.TopicSetter = line.Params[2]; channel.TopicTime = DateTimeOffset @@ -651,27 +810,35 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_TOPIC numeric + /// + /// + /// private Emit HandleTopicNumeric(Line line) { - var emit = new Emit(); - var channelLower = CaseFold(line.Params[1]); - if (Channels.ContainsKey(channelLower)) + var emit = new Emit(); + if (HasChannel(line.Params[1])) { - var channel = Channels[channelLower]; - emit.Channel = channel; - Channels[channelLower].Topic = line.Params[2]; + var channel = GetChannel(line.Params[1]); + emit.Channel = channel; + channel.Topic = line.Params[2]; } return emit; } + /// + /// Handles TOPIC command + /// + /// + /// private Emit HandleTopic(Line line) { - var emit = new Emit(); - var channelLower = CaseFold(line.Params[0]); - if (Channels.ContainsKey(channelLower)) + var emit = new Emit(); + if (HasChannel(line.Params[0])) { - var channel = Channels[channelLower]; + var channel = GetChannel(line.Params[0]); emit.Channel = channel; channel.Topic = line.Params[1]; channel.TopicSetter = line.Hostmask.ToString(); @@ -681,13 +848,17 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_CREATIONTIME numeric + /// + /// + /// private Emit HandleCreationTime(Line line) { - var emit = new Emit(); - var channelLower = CaseFold(line.Params[1]); - if (Channels.ContainsKey(channelLower)) + var emit = new Emit(); + if (HasChannel(line.Params[1])) { - var channel = Channels[channelLower]; + var channel = GetChannel(line.Params[1]); emit.Channel = channel; channel.Created = DateTimeOffset .FromUnixTimeSeconds(int.Parse(line.Params[2], CultureInfo.InvariantCulture)).DateTime; @@ -696,13 +867,17 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_NAMREPLY numeric + /// + /// + /// private Emit HandleNames(Line line) { - var emit = new Emit(); - var channelLower = CaseFold(line.Params[2]); + var emit = new Emit(); + if (!HasChannel(line.Params[2])) return emit; - if (!Channels.ContainsKey(channelLower)) return emit; - var channel = Channels[channelLower]; + var channel = GetChannel(line.Params[2]); emit.Channel = channel; var nicknames = line.Params[3].Split(' ', StringSplitOptions.RemoveEmptyEntries); var users = new List(); @@ -721,17 +896,15 @@ namespace IRCStates } var hostmask = new Hostmask(nick.Substring(modes.Length)); - var nickLower = CaseFold(hostmask.NickName); - if (!Users.ContainsKey(nickLower)) AddUser(hostmask.NickName, nickLower); + var user = GetUser(hostmask.NickName) ?? AddUser(hostmask.NickName); - var user = Users[nickLower]; users.Add(user); var channelUser = UserJoin(channel, user); if (hostmask.UserName != null) user.UserName = hostmask.UserName; if (hostmask.HostName != null) user.HostName = hostmask.HostName; - if (IsMe(nickLower)) SelfHostmask(hostmask); + if (IsMe(hostmask.NickName)) SelfHostmask(hostmask); foreach (var mode in modes.Select(c => c.ToString(CultureInfo.InvariantCulture))) if (!channelUser.Modes.Contains(mode)) @@ -741,6 +914,11 @@ namespace IRCStates return emit; } + /// + /// Handles ERROR command + /// + /// + /// private Emit HandleError(Line line) { Users.Clear(); @@ -748,22 +926,27 @@ namespace IRCStates return new Emit(); } + /// + /// Handles QUIT command + /// + /// + /// private Emit HandleQuit(Line line) { var emit = new Emit(); - var nickLower = CaseFold(line.Hostmask.NickName); + var nick = line.Hostmask.NickName; if (line.Params.Any()) emit.Text = line.Params[0]; - if (IsMe(nickLower) || line.Source == null) + if (IsMe(nick) || line.Source == null) { emit.Self = true; Users.Clear(); Channels.Clear(); } - else if (Users.ContainsKey(nickLower)) + else if (HasUser(nick)) { - var user = Users[nickLower]; - Users.Remove(nickLower); + var user = GetUser(nick); + Users.Remove(user.NickNameLower); emit.User = user; foreach (var channel in user.Channels.Select(c => Channels[c])) channel.Users.Remove(user.NickNameLower); @@ -772,13 +955,23 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_LOGGEDOUT numeric + /// + /// + /// private Emit HandleLoggedOut(Line line) { Account = null; - SelfHostmask(new Hostmask(line.Params[1])); + SelfHostmask(line.Params[1]); return new Emit(); } + /// + /// Handles KICK command + /// + /// + /// private Emit HandleKick(Line line) { var (emit, kicked) = UserPart(line, line.Params[1], line.Params[0], 2); @@ -787,30 +980,37 @@ namespace IRCStates emit.UserTarget = kicked; if (IsMe(kicked.NickName)) emit.Self = true; - var kickerLower = CaseFold(line.Hostmask.NickName); - if (IsMe(kickerLower)) emit.SelfSource = true; + var kicker = line.Hostmask.NickName; + if (IsMe(kicker)) emit.SelfSource = true; - emit.UserSource = Users.ContainsKey(kickerLower) - ? Users[kickerLower] - : CreateUser(line.Hostmask.NickName, kickerLower); + emit.UserSource = GetUser(kicker) ?? CreateUser(kicker); } return emit; } + /// + /// Handles PART command + /// + /// + /// private Emit HandlePart(Line line) { var (emit, user) = UserPart(line, line.Hostmask.NickName, line.Params[0], 1); if (user != null) { emit.User = user; - if (IsMe(user.NickName)) emit.Self = true; + emit.Self = IsMe(user.NickName); } return emit; } - + /// + /// Handles JOIN command + /// + /// + /// private Emit HandleJoin(Line line) { var extended = line.Params.Count == 3; @@ -818,18 +1018,18 @@ namespace IRCStates var realname = extended ? line.Params[2] : null; var emit = new Emit(); - var channelLower = CaseFold(line.Params[0]); - var nickLower = CaseFold(line.Hostmask.NickName); + var channelName = line.Params[0]; + var nick = line.Hostmask.NickName; // handle own join - if (IsMe(nickLower)) + if (IsMe(nick)) { emit.Self = true; - if (!HasChannel(channelLower)) + if (!HasChannel(channelName)) { var channel = new Channel(); - channel.SetName(line.Params[0], channelLower); - Channels[channelLower] = channel; + channel.SetName(channelName, CaseFold(channelName)); + Channels[CaseFold(channelName)] = channel; } SelfHostmask(line.Hostmask); @@ -840,14 +1040,14 @@ namespace IRCStates } } - if (HasChannel(channelLower)) + if (HasChannel(channelName)) { - var channel = Channels[channelLower]; + var channel = GetChannel(channelName); emit.Channel = channel; - if (!HasUser(nickLower)) AddUser(line.Hostmask.NickName, nickLower); + if (!HasUser(nick)) AddUser(nick); - var user = Users[nickLower]; + var user = GetUser(nick); emit.User = user; if (line.Hostmask.UserName != null) user.UserName = line.Hostmask.UserName; if (line.Hostmask.HostName != null) user.HostName = line.Hostmask.HostName; @@ -863,43 +1063,53 @@ namespace IRCStates return emit; } - + /// + /// Handles NICK command + /// + /// + /// private Emit HandleNick(Line line) { - var nick = line.Params[0]; - var nickLower = CaseFold(line.Hostmask.NickName); + var newNick = line.Params[0]; + var oldNick = line.Hostmask.NickName; var emit = new Emit(); - if (Users.ContainsKey(nickLower)) + if (HasUser(oldNick)) { - var user = Users[nickLower]; - Users.Remove(nickLower); - emit.User = user; - + var user = GetUser(oldNick); var oldNickLower = user.NickNameLower; - var newNickLower = CaseFold(nick); - user.SetNickName(nick, newNickLower); + var newNickLower = CaseFold(newNick); + + emit.User = user; + Users.Remove(oldNickLower); Users[newNickLower] = user; + user.SetNickName(newNick, newNickLower); + foreach (var channelLower in user.Channels) { - var channel = Channels[channelLower]; + var channel = GetChannel(channelLower); var channelUser = channel.Users[oldNickLower]; channel.Users.Remove(oldNickLower); channel.Users[newNickLower] = channelUser; } } - if (IsMe(nickLower)) + if (IsMe(oldNick)) { emit.Self = true; - NickName = nick; - NickNameLower = CaseFold(nick); + NickName = newNick; + NickNameLower = CaseFold(newNick); } return emit; } + /// + /// Handles RPL_MOTDSTART and RPL_MOTD numerics + /// + /// + /// private Emit HandleMotd(Line line) { if (line.Command == Numeric.RPL_MOTDSTART) Motd.Clear(); @@ -909,6 +1119,11 @@ namespace IRCStates return emit; } + /// + /// Handles RPL_ISUPPORT numeric + /// + /// + /// private Emit HandleISupport(Line line) { ISupport = new ISupport(); @@ -916,7 +1131,11 @@ namespace IRCStates return new Emit(); } - + /// + /// Handles RPL_WELCOME numeric + /// + /// + /// private Emit HandleWelcome(Line line) { NickName = line.Params[0]; diff --git a/IRCStates/User.cs b/IRCStates/User.cs index 5e18443..97abb15 100644 --- a/IRCStates/User.cs +++ b/IRCStates/User.cs @@ -9,15 +9,15 @@ namespace IRCStates Channels = new HashSet(); } - public string NickName { get; set; } - public string NickNameLower { get; set; } + public string NickName { get; private set; } + public string NickNameLower { get; private set; } public string UserName { get; set; } public string HostName { get; set; } public string RealName { get; set; } public string Account { get; set; } public string Away { get; set; } - public HashSet Channels { get; set; } + public HashSet Channels { get; private set; } public override string ToString() { -- cgit 1.4.1