about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Harris <ben@tilde.team>2020-05-13 14:21:49 -0400
committerBen Harris <ben@tilde.team>2020-05-13 14:30:12 -0400
commitb93174070a0964f254781686ed2390855127ad7a (patch)
treef75f8bbb3949be13ac165b670bbb9ef44a7a2909
parentba63e42be47fe1021e727347477a7df5779d23f7 (diff)
Start adding some line handlers
-rw-r--r--IrcStates/Commands.cs22
-rw-r--r--IrcStates/Emit.cs14
-rw-r--r--IrcStates/HandlesAttribute.cs15
-rw-r--r--IrcStates/ISupport.cs7
-rw-r--r--IrcStates/ISupportPrefix.cs5
-rw-r--r--IrcStates/Server.cs282
6 files changed, 276 insertions, 69 deletions
diff --git a/IrcStates/Commands.cs b/IrcStates/Commands.cs
new file mode 100644
index 0000000..b5bc358
--- /dev/null
+++ b/IrcStates/Commands.cs
@@ -0,0 +1,22 @@
+namespace IrcStates
+{
+    public static class Commands
+    {
+        public const string Nick = "NICK";
+        public const string Join = "JOIN";
+        public const string Mode = "MODE";
+        public const string Part = "PART";
+        public const string Kick = "KICK";
+        public const string Quit = "QUIT";
+        public const string Error = "ERROR";
+        public const string Topic = "TOPIC";
+        public const string Privmsg = "PRIVMSG";
+        public const string Notice = "NOTICE";
+        public const string Tagmsg = "TAGMSG";
+        public const string Chghost = "CHGHOST";
+        public const string Setname = "SETNAME";
+        public const string Away = "AWAY";
+        public const string Account = "ACCOUNT";
+        public const string Cap = "CAP";
+    }
+}
diff --git a/IrcStates/Emit.cs b/IrcStates/Emit.cs
index 3867a61..9ca9cb5 100644
--- a/IrcStates/Emit.cs
+++ b/IrcStates/Emit.cs
@@ -12,13 +12,13 @@ namespace IrcStates
         public bool Self { get; set; }
         public bool SelfSource { get; set; }
         public bool SelfTarget { get; set; }
-        public Tests.User User { get; set; }
-        public Tests.User UserSource { get; set; }
-        public Tests.User UserTarget { get; set; }
-        public List<Tests.User> Users { get; set; }
-        public Tests.Channel Channel { get; set; }
-        public Tests.Channel ChannelSource { get; set; }
-        public Tests.Channel ChannelTarget { get; set; }
+        public User User { get; set; }
+        public User UserSource { get; set; }
+        public User UserTarget { get; set; }
+        public List<User> Users { get; set; }
+        public Channel Channel { get; set; }
+        public Channel ChannelSource { get; set; }
+        public Channel ChannelTarget { get; set; }
         public string Target { get; set; }
     }
 }
diff --git a/IrcStates/HandlesAttribute.cs b/IrcStates/HandlesAttribute.cs
deleted file mode 100644
index 8f3b271..0000000
--- a/IrcStates/HandlesAttribute.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-
-namespace IrcStates
-{
-    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
-    internal class HandlesAttribute : Attribute
-    {
-        private string Command { get; }
-
-        public HandlesAttribute(string command)
-        {
-            Command = command;
-        }
-    }
-}
diff --git a/IrcStates/ISupport.cs b/IrcStates/ISupport.cs
index b9ad502..afb633d 100644
--- a/IrcStates/ISupport.cs
+++ b/IrcStates/ISupport.cs
@@ -31,8 +31,10 @@ namespace IrcStates
         public int? Watch { get; set; }
         public bool Whox { get; set; }
 
-        public void Parse(IList<string> tokens)
+        public void Parse(IEnumerable<string> tokens)
         {
+            if (tokens == null) return;
+            
             foreach (var token in tokens)
             {
                 var split = token.Split('=', 2);
@@ -65,7 +67,8 @@ namespace IrcStates
                         Watch = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
                         break;
                     case "CASEMAPPING":
-                        if (Enum.TryParse(value, true, out Casemap.CaseMapping caseMapping)) CaseMapping = caseMapping;
+                        if (Enum.TryParse(value, true, out Casemap.CaseMapping caseMapping))
+                            CaseMapping = caseMapping;
                         break;
                     case "CHANTYPES":
                         ChanTypes = new List<string> {value};
diff --git a/IrcStates/ISupportPrefix.cs b/IrcStates/ISupportPrefix.cs
index 94668e3..b319e04 100644
--- a/IrcStates/ISupportPrefix.cs
+++ b/IrcStates/ISupportPrefix.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 
 namespace IrcStates
 {
@@ -6,6 +7,8 @@ namespace IrcStates
     {
         public ISupportPrefix(string splitVal)
         {
+            if (splitVal == null) throw new ArgumentNullException(nameof(splitVal));
+
             var split = splitVal.Substring(1).Split(')', 2);
             Modes    = new List<string> {split[0]};
             Prefixes = new List<string> {split[1]};
diff --git a/IrcStates/Server.cs b/IrcStates/Server.cs
index 582237d..a552890 100644
--- a/IrcStates/Server.cs
+++ b/IrcStates/Server.cs
@@ -1,9 +1,7 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
-using System.Reflection;
-using System.Reflection.Metadata.Ecma335;
 using IrcTokens;
 
 namespace IrcStates
@@ -29,12 +27,6 @@ namespace IrcStates
             TempCaps      = new Dictionary<string, string>();
             AvailableCaps = new Dictionary<string, string>();
             AgreedCaps    = new List<string>();
-            RegisterHandlersByAttribute();
-        }
-
-        private void RegisterHandlersByAttribute()
-        {
-            throw new NotImplementedException();
         }
 
         public string Name { get; set; }
@@ -57,42 +49,11 @@ namespace IrcStates
         public ISupport ISupport { get; set; }
         public bool HasCap { get; set; }
 
-        public delegate Emit MessageHandler(Server server, Line line);
-        private Dictionary<string, List<MessageHandler>> Handlers { get; set; }
-
         public override string ToString()
         {
             return $"Server(name={Name})";
         }
 
-        public List<(Line, Emit)> Recv(byte[] data)
-        {
-            if (data == null) return null;
-
-            var lines = _decoder.Push(data, data.Length);
-            if (lines == null) throw new ServerDisconnectedException();
-
-            return lines.Select(l => (l, ParseTokens(l))).ToList();
-        }
-
-        public Emit Parse(Line line)
-        {
-            if (line == null || !Handlers.ContainsKey(line.Command)) return null;
-            var ret = new Emit();
-
-            var handlers = Handlers[line.Command]
-                .Select(callback => callback(this, line))
-                .Where(emit => emit != null);
-
-            foreach (var emit in handlers)
-            {
-                emit.Command = line.Command;
-                ret          = emit;
-            }
-
-            return ret;
-        }
-
         public string CaseFold(string str)
         {
             return Casemap.CaseFold(ISupport.CaseMapping, str);
@@ -142,14 +103,247 @@ namespace IrcStates
             return HasChannel(name) ? Channels[name] : null;
         }
 
-        [Handles(Numeric.RPL_WELCOME)]
+        public List<(Line, Emit)> Recv(byte[] data)
+        {
+            if (data == null) return null;
+
+            var lines = _decoder.Push(data, data.Length);
+            if (lines == null) throw new ServerDisconnectedException();
+
+            return lines.Select(l => (l, Parse(l))).ToList();
+        }
+
+        public Emit Parse(Line line)
+        {
+            if (line == null) return null;
+
+            switch (line.Command)
+            {
+                case Numeric.RPL_WELCOME:  return HandleWelcome(line);
+                case Numeric.RPL_ISUPPORT: return HandleISupport(line);
+                case Numeric.RPL_MOTDSTART:
+                case Numeric.RPL_MOTD:
+                    return HandleMotd(line);
+                case Commands.Nick:             return HandleNick(line);
+                case Commands.Join:             return HandleJoin(line);
+                case Commands.Part:             return HandlePart(line);
+                case Commands.Kick:             return HandleKick(line);
+                case Commands.Quit:             return HandleQuit(line);
+                case Commands.Error:            return HandleError(line);
+                case Numeric.RPL_NAMREPLY:      return HandleNames(line);
+                case Numeric.RPL_CREATIONTIME:  return HandleCreationTime(line);
+                case Commands.Topic:            return HandleTopic(line);
+                case Numeric.RPL_TOPIC:         return HandleTopicNumeric(line);
+                case Numeric.RPL_TOPICWHOTIME:  return HandleTopicTime(line);
+                case Commands.Mode:             return HandleMode(line);
+                case Numeric.RPL_CHANNELMODEIS: return HandleChannelModeIs(line);
+                case Numeric.RPL_UMODEIS:       return HandleUModeIs(line);
+                case Commands.Privmsg:
+                case Commands.Notice:
+                case Commands.Tagmsg:
+                    return HandleMessage(line);
+                case Numeric.RPL_VISIBLEHOST: return HandleVisibleHost(line);
+                case Numeric.RPL_WHOREPLY:    return HandleWhoReply(line);
+                case Numeric.RPL_WHOSPCRPL:   return HandleWhox(line);
+                case Numeric.RPL_WHOISUSER:   return HandleWhoIsUser(line);
+                case Commands.Chghost:        return HandleChghost(line);
+                case Commands.Setname:        return HandleSetname(line);
+                case Commands.Away:           return HandleAway(line);
+                case Commands.Account:        return HandleAccount(line);
+                case Commands.Cap:            return HandleCap(line);
+                case Numeric.RPL_LOGGEDIN:    return HandleLoggedIn(line);
+                case Numeric.RPL_LOGGEDOUT:   return HandleLoggedOut(line);
+            }
+
+            return new Emit();
+        }
+
+        private Emit HandleSetname(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleAway(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleAccount(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleCap(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleLoggedIn(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleChghost(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleWhoIsUser(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleWhox(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleWhoReply(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleVisibleHost(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleMessage(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleUModeIs(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleChannelModeIs(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleMode(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleTopicTime(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleTopicNumeric(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleTopic(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleCreationTime(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleNames(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleError(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleQuit(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleLoggedOut(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleKick(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandlePart(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleJoin(Line line)
+        {
+            throw new NotImplementedException();
+        }
+
+        private Emit HandleNick(Line line)
+        {
+            var nick = line.Params[0];
+            var nickLower = CaseFold(line.Hostmask.NickName);
+
+            var emit = new Emit();
+
+            if (Users.ContainsKey(nickLower))
+            {
+                var user = Users[nick];
+                emit.User = user;
+
+                var oldNickLower = user.NickNameLower;
+                var newNickLower = CaseFold(nick);
+                user.SetNickName(nick, newNickLower);
+                Users[newNickLower] = user;
+                foreach (var channelLower in user.Channels)
+                {
+                    var channel = Channels[channelLower];
+                    var channelUser = channel.Users[oldNickLower];
+                    channel.Users.Remove(oldNickLower);
+                    channel.Users[newNickLower] = channelUser;
+                }
+            }
+
+            if (nickLower == NickNameLower)
+            {
+                emit.Self = true;
+                NickName = nick;
+                NickNameLower = CaseFold(nick);
+            }
+
+            return emit;
+        }
+
+        private Emit HandleMotd(Line line)
+        {
+            if (line.Command == Numeric.RPL_MOTDSTART)
+            {
+                Motd.Clear();
+            }
+
+            var emit = new Emit {Text = line.Params[1]};
+            Motd.Add(line.Params[1]);
+            return emit;
+        }
+
+        private Emit HandleISupport(Line line)
+        {
+            ISupport = new ISupport();
+            ISupport.Parse(line.Params.Skip(1).SkipLast(1));
+            return new Emit();
+        }
+
+
         private Emit HandleWelcome(Line line)
         {
-            NickName = line.Params[0];
+            NickName      = line.Params[0];
             NickNameLower = CaseFold(line.Params[0]);
-            Registered = true;
+            Registered    = true;
             return new Emit();
         }
-
     }
 }