- Add support for "!wm <value>" and "!wm <name>" commands.
[reactos.git] / irc / TechBot / TechBot.Library / IrcService.cs
1 using System;
2 using System.Collections;
3 using System.Threading;
4 using TechBot.IRCLibrary;
5
6 namespace TechBot.Library
7 {
8 public class IrcService : IServiceOutput
9 {
10 private string hostname;
11 private int port;
12 private string channelnames;
13 private string botname;
14 private string chmPath;
15 private string mainChm;
16 private string ntstatusXml;
17 private string winerrorXml;
18 private string hresultXml;
19 private string wmXml;
20 private string svnCommand;
21 private IrcClient client;
22 private ArrayList channels = new ArrayList(); /* IrcChannel */
23 private TechBotService service;
24 private bool isStopped = false;
25
26 public IrcService(string hostname,
27 int port,
28 string channelnames,
29 string botname,
30 string chmPath,
31 string mainChm,
32 string ntstatusXml,
33 string winerrorXml,
34 string hresultXml,
35 string wmXml,
36 string svnCommand)
37 {
38 this.hostname = hostname;
39 this.port = port;
40 this.channelnames = channelnames;
41 this.botname = botname;
42 this.chmPath = chmPath;
43 this.mainChm = mainChm;
44 this.ntstatusXml = ntstatusXml;
45 this.winerrorXml = winerrorXml;
46 this.hresultXml = hresultXml;
47 this.wmXml = wmXml;
48 this.svnCommand = svnCommand;
49 }
50
51 public void Run()
52 {
53 service = new TechBotService(this,
54 chmPath,
55 mainChm,
56 ntstatusXml,
57 winerrorXml,
58 hresultXml,
59 wmXml,
60 svnCommand);
61 service.Run();
62
63 client = new IrcClient();
64 client.Encoding = System.Text.Encoding.GetEncoding("iso-8859-1");
65 client.MessageReceived += new MessageReceivedHandler(client_MessageReceived);
66 client.ChannelUserDatabaseChanged += new ChannelUserDatabaseChangedHandler(client_ChannelUserDatabaseChanged);
67 System.Console.WriteLine(String.Format("Connecting to {0} port {1}",
68 hostname, port));
69 client.Connect(hostname, port);
70 System.Console.WriteLine("Connected...");
71 client.Register(botname, null);
72 System.Console.WriteLine(String.Format("Registered as {0}...", botname));
73 JoinChannels();
74
75 while (!isStopped)
76 {
77 Thread.Sleep(1000);
78 }
79
80 PartChannels();
81 client.Diconnect();
82 System.Console.WriteLine("Disconnected...");
83 }
84
85 public void Stop()
86 {
87 isStopped = true;
88 }
89
90 private void JoinChannels()
91 {
92 foreach (string channelname in channelnames.Split(new char[] { ';' }))
93 {
94 IrcChannel channel = client.JoinChannel(channelname);
95 channels.Add(channel);
96 System.Console.WriteLine(String.Format("Joined channel #{0}...",
97 channel.Name));
98 }
99 }
100
101 private void PartChannels()
102 {
103 foreach (IrcChannel channel in channels)
104 {
105 client.PartChannel(channel, "Caught in the bitstream...");
106 System.Console.WriteLine(String.Format("Parted channel #{0}...",
107 channel.Name));
108 }
109 }
110
111 private string GetMessageSource(MessageContext context)
112 {
113 if (context is ChannelMessageContext)
114 {
115 ChannelMessageContext channelContext = context as ChannelMessageContext;
116 return String.Format("#{0}",
117 channelContext.Channel.Name);
118 }
119 else if (context is UserMessageContext)
120 {
121 UserMessageContext userContext = context as UserMessageContext;
122 return userContext.User.Nickname;
123 }
124 else
125 {
126 throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
127 context.GetType()));
128 }
129 }
130
131 public void WriteLine(MessageContext context,
132 string message)
133 {
134 if (context is ChannelMessageContext)
135 {
136 ChannelMessageContext channelContext = context as ChannelMessageContext;
137 channelContext.Channel.Talk(message);
138 }
139 else if (context is UserMessageContext)
140 {
141 UserMessageContext userContext = context as UserMessageContext;
142 userContext.User.Talk(message);
143 }
144 else
145 {
146 throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
147 context.GetType()));
148 }
149 }
150
151 private void ExtractMessage(string parameters,
152 out string message)
153 {
154 int startIndex = parameters.IndexOf(':');
155 if (startIndex != -1)
156 {
157 message = parameters.Substring(startIndex + 1);
158 }
159 else
160 {
161 message = parameters;
162 }
163 }
164
165 private bool GetChannelName(IrcMessage message,
166 out string channelName)
167 {
168 if (message.Parameters == null || !message.Parameters.StartsWith("#"))
169 {
170 channelName = null;
171 return false;
172 }
173
174 int index = message.Parameters.IndexOf(' ');
175 if (index == -1)
176 index = message.Parameters.Length;
177 else
178 index = index - 1;
179 channelName = message.Parameters.Substring(1, index);
180 return true;
181 }
182
183 private bool GetTargetNickname(IrcMessage message,
184 out string nickname)
185 {
186 if (message.Parameters == null)
187 {
188 nickname = null;
189 return false;
190 }
191
192 int index = message.Parameters.IndexOf(' ');
193 if (index == -1)
194 index = message.Parameters.Length;
195 nickname = message.Parameters.Substring(0, index);
196 Console.WriteLine("nickname: " + nickname);
197 return true;
198 }
199
200 private bool ShouldAcceptMessage(IrcMessage message,
201 out MessageContext context)
202 {
203 if (message.Command.ToUpper().Equals("PRIVMSG"))
204 {
205 string channelName;
206 string nickname;
207 if (GetChannelName(message,
208 out channelName))
209 {
210 foreach (IrcChannel channel in channels)
211 {
212 if (String.Compare(channel.Name, channelName, true) == 0)
213 {
214 context = new ChannelMessageContext(channel);
215 return true;
216 }
217 }
218 }
219 else if (GetTargetNickname(message,
220 out nickname))
221 {
222 IrcUser targetUser = new IrcUser(client,
223 nickname);
224 if (String.Compare(targetUser.Nickname, botname, true) == 0)
225 {
226 IrcUser sourceUser = new IrcUser(client,
227 message.PrefixNickname);
228 context = new UserMessageContext(sourceUser);
229 return true;
230 }
231 }
232 }
233 context = null;
234 return false;
235 }
236
237 private void client_MessageReceived(IrcMessage message)
238 {
239 try
240 {
241 if (message.Command != null &&
242 message.Parameters != null)
243 {
244 string injectMessage;
245 ExtractMessage(message.Parameters,
246 out injectMessage);
247 MessageContext context;
248 if (ShouldAcceptMessage(message,
249 out context))
250 {
251 Console.WriteLine(String.Format("Injecting: {0} from {1}",
252 injectMessage,
253 GetMessageSource(context)));
254 service.InjectMessage(context,
255 injectMessage);
256 }
257 else
258 {
259 Console.WriteLine("Received: " + message.Line);
260 }
261 }
262 else
263 {
264 Console.WriteLine("Received: " + message.Line);
265 }
266 }
267 catch (Exception ex)
268 {
269 Console.WriteLine(String.Format("Exception: {0}", ex));
270 }
271 }
272
273 private void client_ChannelUserDatabaseChanged(IrcChannel channel)
274 {
275 }
276 }
277 }