1 module ircbod.socket;
2 
3 import std.socket, std.socketstream, std.conv, std.string;
4 
5 class IRCSocket
6 {
7 private:
8 
9     char[]         host;
10     ushort         port;
11     TcpSocket      sock;
12     SocketStream   stream;
13 
14 public:
15 
16     this(char[] host, ushort port = 6667)
17     {
18         this.host = host;
19         this.port = port;
20         this.sock = null;
21     }
22 
23     bool connected() {
24         return this.sock !is null;
25     }
26 
27     bool connect()
28     {
29         this.sock   = new TcpSocket(new InternetAddress(this.host, this.port));
30         this.stream = new SocketStream(this.sock);
31         return true;
32     }
33 
34     bool disconnect()
35     {
36         if (connected()) {
37             this.sock.close();
38             this.sock = null;
39             return true;
40         }
41         return false;
42     }
43 
44     void close()
45     {
46         disconnect();
47     }
48 
49     bool reconnect()
50     {
51         disconnect();
52         return connect();
53     }
54 
55     string read()
56     {
57         return to!string(this.stream.readLine()).chomp();
58     }
59 
60     private void write(string message)
61     {
62         std.stdio.writeln(">> " , message);
63         this.stream.writeString(message ~ "\r\n");
64     }
65 
66     void raw(string[] args)
67     {
68         auto last = args[$ - 1];
69         if (last) {
70             args[$ - 1] = ":" ~ last;
71         }
72         write(args.join(" "));
73     }
74 
75     private void writeOptional(string command, string[] optional = [])
76     {
77         if(optional.length > 0) {
78             command ~= " " ~ optional.join(" ");
79         }
80         write(command.strip());
81     }
82 
83     void pass(string password)
84     {
85         write("PASS " ~ password);
86     }
87 
88     void nick(string nickname)
89     {
90         write("NICK " ~ nickname);
91     }
92 
93     void user(string username, uint mode, string unused, string realname)
94     {
95         write("USER " ~ [username, to!string(mode), unused, ":" ~ realname].join(" "));
96     }
97 
98     void oper(string name, string password)
99     {
100         write("OPER " ~ name ~ " " ~ password);
101     }
102 
103     void mode(string channel, string[] modes)
104     {
105         write("MODE " ~ channel ~ " " ~ modes.join(" "));
106     }
107 
108     void quit(string message = null)
109     {
110         raw(["QUIT", message]);
111     }
112 
113     void join(string channel, string password = "")
114     {
115         writeOptional("JOIN " ~ channel, [password]);
116     }
117 
118     void part(string channel, string message = "")
119     {
120         raw(["PART", channel, message]);
121     }
122 
123     void topic(string channel, string topic = "")
124     {
125         raw(["TOPIC", channel, topic]);
126     }
127 
128     void names(string[] channels)
129     {
130         if(channels.length > 0)
131             write("NAMES " ~ channels.join(","));
132         else
133             write("NAMES");
134     }
135 
136     void list(string[] channels)
137     {
138         if(channels.length > 0)
139             write("LIST " ~ channels.join(","));
140         else
141             write("LIST");
142     }
143 
144     void invite(string nickname, string channel)
145     {
146         write("INVITE " ~ nickname ~ " " ~ channel);
147     }
148 
149     void kick(string channel, string nickname, string comment = null)
150     {
151         raw(["KICK", channel, nickname, comment]);
152     }
153 
154     void privmsg(string target, string message)
155     {
156         write("PRIVMSG " ~ target ~ " :" ~ message);
157     }
158 
159     void notice(string target, string message)
160     {
161         write("NOTICE " ~ target ~ " :" ~ message);
162     }
163 
164     void motd(string target = null)
165     {
166         writeOptional("MOTD", [target]);
167     }
168 
169     void stats(string[] params)
170     {
171         writeOptional("STATS", params);
172     }
173 
174     void time(string target = null)
175     {
176         writeOptional("TIME", [target]);
177     }
178 
179     void info(string target = null)
180     {
181         writeOptional("INFO", [target]);
182     }
183 
184     void squery(string target, string message)
185     {
186         write("SQUERY " ~ target ~ " :" ~ message);
187     }
188 
189     void who(string[] params)
190     {
191         writeOptional("WHO", params);
192     }
193 
194     void whois(string[] params)
195     {
196         writeOptional("WHOIS", params);
197     }
198 
199     void whowas(string[] params)
200     {
201         writeOptional("WHOWAS", params);
202     }
203 
204     void kill(string user, string message)
205     {
206         write("KILL " ~ user ~ " :" ~ message);
207     }
208 
209     void ping(string server)
210     {
211         write("PING " ~ server);
212     }
213 
214     void pong(string server)
215     {
216         write("PONG " ~ server);
217     }
218 
219     void away(string message = null)
220     {
221         raw(["AWAY", message]);
222     }
223 
224     void users(string target = null)
225     {
226         writeOptional("USERS", [target]);
227     }
228 
229     void userhost(string[] users)
230     {
231         write("USERHOST" ~ users.join(" "));
232     }
233 }