about summary refs log tree commit diff
path: root/IrcStates/Server.cs
blob: 1d4f90ffde92be0a80d52b8bc993b6b2a408ba39 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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();
        }

    }
}