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