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 TempCaps; public Server(string name) { Name = name; Registered = false; Modes = new List(); Motd = new List(); _decoder = new StatefulDecoder(); Users = new Dictionary(); Channels = new Dictionary(); ISupport = new ISupport(); HasCap = false; TempCaps = new Dictionary(); AvailableCaps = new Dictionary(); AgreedCaps = new List(); 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 Modes { get; set; } public List Motd { get; set; } public Dictionary Users { get; set; } public Dictionary Channels { get; set; } public Dictionary AvailableCaps { get; set; } public List AgreedCaps { get; set; } public ISupport ISupport { get; set; } public bool HasCap { get; set; } public delegate Emit MessageHandler(Server server, Line line); private Dictionary> 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(); } } }