- code refactoring
[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 ChannelMessageContext channelContext = context as ChannelMessageContext;
18 channelContext.Channel.Talk(message);
19 }
20 else if (context is UserMessageContext)
21 {
22 UserMessageContext userContext = context as UserMessageContext;
23 userContext.User.Talk(message);
24 }
25 else
26 {
27 throw new InvalidOperationException(String.Format("Unhandled message context '{0}'",
28 context.GetType()));
29 }
30 }
31 }
32
33 public class IrcTechBotService : TechBotService
34 {
35 private int port;
36 private string hostname;
37 private string channelnames;
38 private string botname;
39 private string password;
40 private string chmPath;
41 private string mainChm;
42 private IrcClient m_IrcClient;
43 private ArrayList channels = new ArrayList();
44 private bool isStopped = false;
45
46 public IrcTechBotService(string hostname,
47 int port,
48 string channelnames,
49 string botname,
50 string password,
51 string chmPath,
52 string mainChm)
53 : base (new IrcServiceOutput() , chmPath , mainChm)
54 {
55 this.hostname = hostname;
56 this.port = port;
57 this.channelnames = channelnames;
58 this.botname = botname;
59 if (password == null || password.Trim() == "")
60 this.password = null;
61 else
62 this.password = password;
63 this.chmPath = chmPath;
64 this.mainChm = mainChm;
65 }
66
67 public override void Run()
68 {
69 //Call the base class
70 base.Run();
71
72 m_IrcClient = new IrcClient();
73 m_IrcClient.Encoding = Encoding.GetEncoding("iso-8859-1");
74 m_IrcClient.MessageReceived += new MessageReceivedHandler(client_MessageReceived);
75 m_IrcClient.ChannelUserDatabaseChanged += new ChannelUserDatabaseChangedHandler(client_ChannelUserDatabaseChanged);
76 Console.WriteLine("Connecting to {0} port {1}",
77 hostname,
78 port);
79 m_IrcClient.Connect(hostname, port);
80 Console.WriteLine("Connected...");
81 m_IrcClient.Register(botname, password, null);
82 Console.WriteLine("Registered as {0}...", botname);
83 JoinChannels();
84
85 while (!isStopped)
86 {
87 Thread.Sleep(1000);
88 }
89
90 PartChannels();
91 m_IrcClient.Diconnect();
92 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 = m_IrcClient.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 m_IrcClient.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 private void ExtractMessage(string parameters,
142 out string message)
143 {
144 int startIndex = parameters.IndexOf(':');
145 if (startIndex != -1)
146 {
147 message = parameters.Substring(startIndex + 1);
148 }
149 else
150 {
151 message = parameters;
152 }
153 }
154
155 private bool GetChannelName(IrcMessage message,
156 out string channelName)
157 {
158 if (message.Parameters == null || !message.Parameters.StartsWith("#"))
159 {
160 channelName = null;
161 return false;
162 }
163
164 int index = message.Parameters.IndexOf(' ');
165 if (index == -1)
166 index = message.Parameters.Length;
167 else
168 index = index - 1;
169 channelName = message.Parameters.Substring(1, index);
170 return true;
171 }
172
173 private bool GetTargetNickname(IrcMessage message,
174 out string nickname)
175 {
176 if (message.Parameters == null)
177 {
178 nickname = null;
179 return false;
180 }
181
182 int index = message.Parameters.IndexOf(' ');
183 if (index == -1)
184 index = message.Parameters.Length;
185 nickname = message.Parameters.Substring(0, index);
186 Console.WriteLine("nickname: " + nickname);
187 return true;
188 }
189
190 private bool ShouldAcceptMessage(IrcMessage message,
191 out MessageContext context)
192 {
193 if (message.Command.ToUpper().Equals("PRIVMSG"))
194 {
195 string channelName;
196 string nickname;
197 if (GetChannelName(message,
198 out channelName))
199 {
200 foreach (IrcChannel channel in channels)
201 {
202 if (String.Compare(channel.Name, channelName, true) == 0)
203 {
204 context = new ChannelMessageContext(channel);
205 return true;
206 }
207 }
208 }
209 else if (GetTargetNickname(message,
210 out nickname))
211 {
212 IrcUser targetUser = new IrcUser(m_IrcClient,
213 nickname);
214 if (String.Compare(targetUser.Nickname, botname, true) == 0)
215 {
216 IrcUser sourceUser = new IrcUser(m_IrcClient,
217 message.PrefixNickname);
218 context = new UserMessageContext(sourceUser);
219 return true;
220 }
221 }
222 }
223 context = null;
224 return false;
225 }
226
227 private void client_MessageReceived(IrcMessage message)
228 {
229 try
230 {
231 if (message.Command != null &&
232 message.Parameters != null)
233 {
234 string injectMessage;
235 ExtractMessage(message.Parameters,
236 out injectMessage);
237 MessageContext context;
238 if (ShouldAcceptMessage(message,
239 out context))
240 {
241 Console.WriteLine(String.Format("Injecting: {0} from {1}",
242 injectMessage,
243 GetMessageSource(context)));
244 InjectMessage(context,
245 injectMessage);
246 }
247 else
248 {
249 Console.WriteLine("Received: " + message.Line);
250 }
251 }
252 else
253 {
254 Console.WriteLine("Received: " + message.Line);
255 }
256 }
257 catch (Exception ex)
258 {
259 Console.WriteLine(String.Format("Exception: {0}", ex));
260 }
261 }
262
263 private void client_ChannelUserDatabaseChanged(IrcChannel channel)
264 {
265 }
266 }
267 }