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