about summary refs log blame commit diff
path: root/IrcStates/Server.cs
blob: 1d4f90ffde92be0a80d52b8bc993b6b2a408ba39 (plain) (tree)
1
2
3
4
5
6
7
8
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
{
    public class Server
    {
        public const string WhoType = "525"; // randomly generated
        private readonly StatefulDecoder _decoder;

        private Dictionary<string, string> TempCaps;

        public Server(string name)
        {
            Name          = name;
            Registered    = false;
            Modes         = new List<string>();
            Motd          = new List<string>();
            _decoder      = new StatefulDecoder();
            Users         = new Dictionary<string, User>();
            Channels      = new Dictionary<string, Channel>();
            ISupport      = new ISupport();
            HasCap        = false;
            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; }
        public string NickName { get; set; }
        public string NickNameLower { get; 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 bool Registered { get; set; }
        public List<string> Modes { get; set; }
        public List<string> Motd { get; set; }
        public Dictionary<string, User> Users { get; set; }
        public Dictionary<string, Channel> Channels { get; set; }
        public Dictionary<string, string> AvailableCaps { get; set; }
        public List<string> AgreedCaps { get; set; }

        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 ParseTokens(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);
        }

        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();
        }

    }
}