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