From 023e29ab75f1f413f918346edaddafdf8b1df5ee Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 13 May 2020 23:34:33 -0400 Subject: implement some stuff --- IrcStates/Server.cs | 220 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 204 insertions(+), 16 deletions(-) (limited to 'IrcStates/Server.cs') diff --git a/IrcStates/Server.cs b/IrcStates/Server.cs index a552890..ea7dd9e 100644 --- a/IrcStates/Server.cs +++ b/IrcStates/Server.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.Serialization; using IrcTokens; namespace IrcStates @@ -103,6 +104,55 @@ namespace IrcStates return HasChannel(name) ? Channels[name] : null; } + private ChannelUser UserJoin(Channel channel, User user) + { + var channelUser = new ChannelUser(); + user.Channels.Add(CaseFold(channel.Name)); + channel.Users[user.NickNameLower] = channelUser; + return channelUser; + } + + private void SelfHostmask(Hostmask hostmask) + { + NickName = hostmask.NickName; + if (hostmask.UserName != null) UserName = hostmask.UserName; + if (hostmask.HostName != null) HostName = hostmask.HostName; + } + + private (Emit, User) UserPart(Line line, string nickName, string channelName, int reasonIndex) + { + var emit = new Emit(); + var channelLower = CaseFold(channelName); + if (line.Params.Count >= reasonIndex + 1) emit.Text = line.Params[reasonIndex]; + + User user = null; + if (HasChannel(channelName)) + { + var channel = Channels[channelLower]; + emit.Channel = channel; + var nickLower = CaseFold(nickName); + if (HasUser(nickLower)) + { + user = Users[nickLower]; + user.Channels.Remove(channelLower); + channel.Users.Remove(nickLower); + if (!user.Channels.Any()) Users.Remove(nickLower); + } + + if (nickLower == NickNameLower) + { + Channels.Remove(channelLower); + foreach (var userToRemove in channel.Users.Keys.Select(u => Users[u])) + { + userToRemove.Channels.Remove(channelLower); + if (!userToRemove.Channels.Any()) Users.Remove(userToRemove.NickNameLower); + } + } + } + + return (emit, user); + } + public List<(Line, Emit)> Recv(byte[] data) { if (data == null) return null; @@ -250,17 +300,87 @@ namespace IrcStates private Emit HandleNames(Line line) { - throw new NotImplementedException(); + var emit = new Emit(); + var channelLower = CaseFold(line.Params[2]); + + if (!Channels.ContainsKey(channelLower)) return emit; + var channel = Channels[channelLower]; + emit.Channel = channel; + var nicknames = line.Params[3].Split(' ', StringSplitOptions.RemoveEmptyEntries); + var users = new List(); + emit.Users = users; + + foreach (var nick in nicknames) + { + var modes = ""; + foreach (var c in nick) + { + var mode = ISupport.Prefix.FromPrefix(c); + if (mode != null) + modes += mode; + else + break; + } + + var hostmask = new Hostmask(nick.Substring(modes.Length)); + var nickLower = CaseFold(hostmask.NickName); + if (!Users.ContainsKey(nickLower)) + { + AddUser(hostmask.NickName, nickLower); + } + + 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 (nickLower == NickNameLower) SelfHostmask(hostmask); + + foreach (var mode in modes.Select(c => c.ToString(CultureInfo.InvariantCulture))) + { + if (!channelUser.Modes.Contains(mode)) + { + channelUser.Modes.Add(mode); + } + } + } + + return emit; } private Emit HandleError(Line line) { - throw new NotImplementedException(); + Users.Clear(); + Channels.Clear(); + return new Emit(); } private Emit HandleQuit(Line line) { - throw new NotImplementedException(); + var emit = new Emit(); + var nickLower = CaseFold(line.Hostmask.NickName); + if (line.Params.Any()) emit.Text = line.Params[0]; + + if (nickLower == NickNameLower || line.Source == null) + { + emit.Self = true; + Users.Clear(); + Channels.Clear(); + } + else if (Users.ContainsKey(nickLower)) + { + var user = Users[nickLower]; + Users.Remove(nickLower); + emit.User = user; + foreach (var channel in user.Channels.Select(c => Channels[c])) + { + channel.Users.Remove(user.NickNameLower); + } + } + + return emit; } private Emit HandleLoggedOut(Line line) @@ -270,29 +390,100 @@ namespace IrcStates private Emit HandleKick(Line line) { - throw new NotImplementedException(); + var (emit, kicked) = UserPart(line, line.Params[1], line.Params[0], 2); + if (kicked != null) + { + emit.UserTarget = kicked; + if (kicked.NickNameLower == NickNameLower) emit.Self = true; + + var kickerLower = CaseFold(line.Hostmask.NickName); + if (kickerLower == NickNameLower) emit.SelfSource = true; + + emit.UserSource = Users.ContainsKey(kickerLower) + ? Users[kickerLower] + : CreateUser(line.Hostmask.NickName, kickerLower); + } + + return emit; } private Emit HandlePart(Line line) { - throw new NotImplementedException(); + var (emit, user) = UserPart(line, line.Hostmask.NickName, line.Params[0], 1); + if (user != null) + { + emit.User = user; + if (user.NickNameLower == NickNameLower) emit.Self = true; + } + + return emit; } + private Emit HandleJoin(Line line) { - throw new NotImplementedException(); + var extended = line.Params.Count == 3; + var account = extended ? line.Params[1].Trim('*') : null; + var realname = extended ? line.Params[2] : null; + var emit = new Emit(); + + var channelLower = CaseFold(line.Params[0]); + var nickLower = CaseFold(line.Hostmask.NickName); + + // handle own join + if (nickLower == NickNameLower) + { + emit.Self = true; + if (!HasChannel(channelLower)) + { + var channel = new Channel(); + channel.SetName(line.Params[0], channelLower); + Channels[channelLower] = channel; + } + + SelfHostmask(line.Hostmask); + if (extended) + { + Account = account; + RealName = realname; + } + } + + if (HasChannel(channelLower)) + { + var channel = Channels[channelLower]; + emit.Channel = channel; + + if (!HasUser(nickLower)) AddUser(line.Hostmask.NickName, nickLower); + + var user = Users[nickLower]; + emit.User = user; + if (line.Hostmask.UserName != null) user.UserName = line.Hostmask.UserName; + if (line.Hostmask.HostName != null) user.HostName = line.Hostmask.HostName; + if (extended) + { + user.Account = account; + user.RealName = realname; + } + + UserJoin(channel, user); + } + + return emit; } + private Emit HandleNick(Line line) { - var nick = line.Params[0]; + var nick = line.Params[0]; var nickLower = CaseFold(line.Hostmask.NickName); var emit = new Emit(); if (Users.ContainsKey(nickLower)) { - var user = Users[nick]; + var user = Users[nickLower]; + Users.Remove(nickLower); emit.User = user; var oldNickLower = user.NickNameLower; @@ -301,7 +492,7 @@ namespace IrcStates Users[newNickLower] = user; foreach (var channelLower in user.Channels) { - var channel = Channels[channelLower]; + var channel = Channels[channelLower]; var channelUser = channel.Users[oldNickLower]; channel.Users.Remove(oldNickLower); channel.Users[newNickLower] = channelUser; @@ -310,8 +501,8 @@ namespace IrcStates if (nickLower == NickNameLower) { - emit.Self = true; - NickName = nick; + emit.Self = true; + NickName = nick; NickNameLower = CaseFold(nick); } @@ -320,10 +511,7 @@ namespace IrcStates private Emit HandleMotd(Line line) { - if (line.Command == Numeric.RPL_MOTDSTART) - { - Motd.Clear(); - } + if (line.Command == Numeric.RPL_MOTDSTART) Motd.Clear(); var emit = new Emit {Text = line.Params[1]}; Motd.Add(line.Params[1]); @@ -333,7 +521,7 @@ namespace IrcStates private Emit HandleISupport(Line line) { ISupport = new ISupport(); - ISupport.Parse(line.Params.Skip(1).SkipLast(1)); + ISupport.Parse(line.Params); return new Emit(); } -- cgit 1.4.1