about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Harris <ben@tilde.team>2020-05-06 21:27:36 -0400
committerBen Harris <ben@tilde.team>2020-05-06 21:27:36 -0400
commitf6f3e7e0c535aaf3627f815dd63970aec6c73f75 (patch)
tree54b7790cb6ebcc26e02d97f24ae8d09fc67163de
parent0117d9d9a0a395166e15c0996f87af823928d011 (diff)
start impl
-rw-r--r--IrcStates/Extensions.cs32
-rw-r--r--IrcStates/HandlesAttribute.cs15
-rw-r--r--IrcStates/Server.cs80
3 files changed, 119 insertions, 8 deletions
diff --git a/IrcStates/Extensions.cs b/IrcStates/Extensions.cs
new file mode 100644
index 0000000..dde0edb
--- /dev/null
+++ b/IrcStates/Extensions.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace IrcStates
+{
+    public static class Extensions
+    {
+        public static Delegate CreateDelegate(this MethodInfo methodInfo, object target)
+        {
+            if (methodInfo == null) return null;
+
+            var types = methodInfo.GetParameters().Select(p => p.ParameterType);
+
+            Func<Type[], Type> getType;
+            if (methodInfo.ReturnType == typeof(void))
+            {
+                getType = Expression.GetActionType;
+            }
+            else
+            {
+                getType = Expression.GetFuncType;
+                types   = types.Concat(new[] {methodInfo.ReturnType});
+            }
+
+            return methodInfo.IsStatic
+                ? Delegate.CreateDelegate(getType(types.ToArray()), methodInfo)
+                : Delegate.CreateDelegate(getType(types.ToArray()), target, methodInfo);
+        }
+    }
+}
diff --git a/IrcStates/HandlesAttribute.cs b/IrcStates/HandlesAttribute.cs
new file mode 100644
index 0000000..8f3b271
--- /dev/null
+++ b/IrcStates/HandlesAttribute.cs
@@ -0,0 +1,15 @@
+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/Server.cs b/IrcStates/Server.cs
index 7199668..1d4f90f 100644
--- a/IrcStates/Server.cs
+++ b/IrcStates/Server.cs
@@ -1,6 +1,9 @@
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata.Ecma335;
 using IrcTokens;
 
 namespace IrcStates
@@ -10,8 +13,6 @@ namespace IrcStates
         public const string WhoType = "525"; // randomly generated
         private readonly StatefulDecoder _decoder;
 
-        public Dictionary<string, List<Func<string, Line, Emit>>> LineHandlers;
-
         private Dictionary<string, string> TempCaps;
 
         public Server(string name)
@@ -21,7 +22,6 @@ namespace IrcStates
             Modes         = new List<string>();
             Motd          = new List<string>();
             _decoder      = new StatefulDecoder();
-            LineHandlers  = new Dictionary<string, List<Func<string, Line, Emit>>>();
             Users         = new Dictionary<string, User>();
             Channels      = new Dictionary<string, Channel>();
             ISupport      = new ISupport();
@@ -29,6 +29,12 @@ 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; }
@@ -51,6 +57,9 @@ 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})";
@@ -58,20 +67,21 @@ namespace IrcStates
 
         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();
 
-            var emits = lines.Select(ParseTokens).ToList();
-            return null;
+            return lines.Select(l => (l, ParseTokens(l))).ToList();
         }
 
         public Emit ParseTokens(Line line)
         {
-            if (line != null && !LineHandlers.ContainsKey(line.Command)) return null;
+            if (line == null || !Handlers.ContainsKey(line.Command)) return null;
             var ret = new Emit();
 
-            var handlers = LineHandlers[line.Command]
-                .Select(callback => callback(line.Command, line))
+            var handlers = Handlers[line.Command]
+                .Select(callback => callback(this, line))
                 .Where(emit => emit != null);
 
             foreach (var emit in handlers)
@@ -87,5 +97,59 @@ namespace IrcStates
         {
             return Casemap.CaseFold(ISupport.CaseMapping, str);
         }
+
+        public bool CaseFoldEquals(string s1, string s2)
+        {
+            return CaseFold(s1) == CaseFold(s2);
+        }
+
+        public bool IsMe(string nickname)
+        {
+            return CaseFold(nickname) == NickNameLower;
+        }
+
+        public bool HasUser(string nickname)
+        {
+            return Users.ContainsKey(CaseFold(nickname));
+        }
+
+        private void AddUser(string nickname, string nicknameLower)
+        {
+            var user = CreateUser(nickname, nicknameLower);
+            Users[nicknameLower] = user;
+        }
+
+        private User CreateUser(string nickname, string nicknameLower)
+        {
+            var user = new User();
+            user.SetNickName(nickname, nicknameLower);
+            return user;
+        }
+
+        public bool IsChannel(string target)
+        {
+            return !string.IsNullOrEmpty(target) &&
+                   ISupport.ChanTypes.Contains(target[0].ToString(CultureInfo.InvariantCulture));
+        }
+
+        public bool HasChannel(string name)
+        {
+            return Channels.ContainsKey(CaseFold(name));
+        }
+
+        public Channel GetChannel(string name)
+        {
+            return HasChannel(name) ? Channels[name] : null;
+        }
+
+        [Handles(Numeric.RPL_WELCOME)]
+        private Emit HandleWelcome(Line line)
+        {
+            NickName = line.Params[0];
+            NickNameLower = CaseFold(line.Params[0]);
+            Registered = true;
+            return new Emit();
+        }
+
     }
 }