diff options
author | Dr Scofield | 2008-10-20 17:31:54 +0000 |
---|---|---|
committer | Dr Scofield | 2008-10-20 17:31:54 +0000 |
commit | 72a388a7b6dfba8f93ffc5c5c45db4c44bb46480 (patch) | |
tree | db9ab06f6820806d8c2b3fc32029383971e955b7 /OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs | |
parent | Mantis #2438 (diff) | |
download | opensim-SC_OLD-72a388a7b6dfba8f93ffc5c5c45db4c44bb46480.zip opensim-SC_OLD-72a388a7b6dfba8f93ffc5c5c45db4c44bb46480.tar.gz opensim-SC_OLD-72a388a7b6dfba8f93ffc5c5c45db4c44bb46480.tar.bz2 opensim-SC_OLD-72a388a7b6dfba8f93ffc5c5c45db4c44bb46480.tar.xz |
cleaning up IRCBridgeModule to allow for configuration from in-world,
chat relaying via private channels, and old IRCBridgeModule
behaviour. also cleaning up IRCBridgeModule's OpenSim.ini
configuration variable names (still supporting "old" variable
names). refactored IRCChatModule into IRCConnector and incorporating
watchdog from IRCBridgeModule into IRCConnector.
enabling ChatModule to be used as a super-class and utilizing it in
ConciergeModule.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs | 710 |
1 files changed, 710 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs new file mode 100644 index 0000000..0eb303c --- /dev/null +++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs | |||
@@ -0,0 +1,710 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Net.Sockets; | ||
32 | using System.Reflection; | ||
33 | using System.Text.RegularExpressions; | ||
34 | using System.Threading; | ||
35 | using OpenMetaverse; | ||
36 | using log4net; | ||
37 | using Nini.Config; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Region.Environment.Interfaces; | ||
40 | using OpenSim.Region.Environment.Scenes; | ||
41 | |||
42 | namespace OpenSim.Region.Environment.Modules.Avatar.Chat | ||
43 | { | ||
44 | public class IRCConnector | ||
45 | { | ||
46 | #region ErrorReplies enum | ||
47 | |||
48 | public enum ErrorReplies | ||
49 | { | ||
50 | NotRegistered = 451, // ":You have not registered" | ||
51 | NicknameInUse = 433 // "<nick> :Nickname is already in use" | ||
52 | } | ||
53 | |||
54 | #endregion | ||
55 | |||
56 | #region Replies enum | ||
57 | |||
58 | public enum Replies | ||
59 | { | ||
60 | MotdStart = 375, // ":- <server> Message of the day - " | ||
61 | Motd = 372, // ":- <text>" | ||
62 | EndOfMotd = 376 // ":End of /MOTD command" | ||
63 | } | ||
64 | |||
65 | #endregion | ||
66 | |||
67 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
68 | |||
69 | private Thread m_listener = null; | ||
70 | private Thread m_watchdog = null; | ||
71 | private Thread m_pinger = null; | ||
72 | |||
73 | private bool m_randomizeNick = true; | ||
74 | |||
75 | public string m_baseNick = null; | ||
76 | private string m_nick = null; | ||
77 | public string Nick | ||
78 | { | ||
79 | get { return m_baseNick; } | ||
80 | set { m_baseNick = value; } | ||
81 | } | ||
82 | |||
83 | private bool m_enabled = false; | ||
84 | public bool Enabled | ||
85 | { | ||
86 | get { return m_enabled; } | ||
87 | } | ||
88 | |||
89 | private bool m_connected = false; | ||
90 | public bool Connected | ||
91 | { | ||
92 | get { return m_connected; } | ||
93 | } | ||
94 | |||
95 | private string m_ircChannel; | ||
96 | public string IrcChannel | ||
97 | { | ||
98 | get { return m_ircChannel; } | ||
99 | |||
100 | set { m_ircChannel = value; } | ||
101 | } | ||
102 | |||
103 | private bool m_relayPrivateChannels = false; | ||
104 | public bool RelayPrivateChannels | ||
105 | { | ||
106 | get { return m_relayPrivateChannels; } | ||
107 | set { m_relayPrivateChannels = value; } | ||
108 | } | ||
109 | |||
110 | private int m_relayChannel = 0; | ||
111 | public int RelayChannel | ||
112 | { | ||
113 | get { return m_relayChannel; } | ||
114 | set { m_relayChannel = value; } | ||
115 | } | ||
116 | |||
117 | private bool m_clientReporting = true; | ||
118 | public bool ClientReporting | ||
119 | { | ||
120 | get { return m_clientReporting; } | ||
121 | set { m_clientReporting = value; } | ||
122 | } | ||
123 | |||
124 | private uint m_port = 6667; | ||
125 | public uint Port | ||
126 | { | ||
127 | get { return m_port; } | ||
128 | set { m_port = value; } | ||
129 | } | ||
130 | |||
131 | private string m_server = null; | ||
132 | public string Server | ||
133 | { | ||
134 | get { return m_server; } | ||
135 | set { m_server = value; } | ||
136 | } | ||
137 | |||
138 | public string m_accessPassword = "badkitty"; | ||
139 | |||
140 | private string m_privmsgformat = "PRIVMSG {0} :<{1} in {2}>: {3}"; | ||
141 | private StreamReader m_reader; | ||
142 | private List<Scene> m_scenes = new List<Scene>(); | ||
143 | |||
144 | private NetworkStream m_stream = null; | ||
145 | internal object m_syncConnect = new object(); | ||
146 | private TcpClient m_tcp; | ||
147 | private string m_user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; | ||
148 | private StreamWriter m_writer; | ||
149 | |||
150 | |||
151 | public IRCConnector(IConfigSource config) | ||
152 | { | ||
153 | m_tcp = null; | ||
154 | m_writer = null; | ||
155 | m_reader = null; | ||
156 | |||
157 | // configuration in OpenSim.ini | ||
158 | // [IRC] | ||
159 | // server = chat.freenode.net | ||
160 | // nick = OSimBot_mysim | ||
161 | // nicknum = true | ||
162 | // ;nicknum set to true appends a 2 digit random number to the nick | ||
163 | // ;username = USER OpenSimBot 8 * :I'm a OpenSim to irc bot | ||
164 | // ; username is the IRC command line sent | ||
165 | // ; USER <irc_user> <visible=8,invisible=0> * : <IRC_realname> | ||
166 | // channel = #opensim-regions | ||
167 | // port = 6667 | ||
168 | // ;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message | ||
169 | // ;for <bot>:<user in region> :<message> | ||
170 | // ;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" | ||
171 | // ;for <bot>:<message> - <user of region> : | ||
172 | // ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" | ||
173 | // ;for <bot>:<message> - from <user> : | ||
174 | // ;msgformat = "PRIVMSG {0} : {3} - from {1}" | ||
175 | // Traps I/O disconnects so it does not crash the sim | ||
176 | // Trys to reconnect if disconnected and someone says something | ||
177 | // Tells IRC server "QUIT" when doing a close (just to be nice) | ||
178 | // Default port back to 6667 | ||
179 | |||
180 | try | ||
181 | { | ||
182 | m_server = config.Configs["IRC"].GetString("server"); | ||
183 | m_baseNick = config.Configs["IRC"].GetString("nick", "OSimBot"); | ||
184 | |||
185 | m_randomizeNick = config.Configs["IRC"].GetBoolean("randomize_nick", m_randomizeNick); | ||
186 | m_randomizeNick = config.Configs["IRC"].GetBoolean("nicknum", m_randomizeNick); // compat | ||
187 | m_ircChannel = config.Configs["IRC"].GetString("channel"); | ||
188 | m_port = (uint)config.Configs["IRC"].GetInt("port", (int)m_port); | ||
189 | m_user = config.Configs["IRC"].GetString("username", m_user); | ||
190 | m_privmsgformat = config.Configs["IRC"].GetString("msgformat", m_privmsgformat); | ||
191 | // m_commandChannel = config.Configs["IRC"].GetInt("commandchannel", m_commandChannel); | ||
192 | |||
193 | // m_verbosity = config.Configs["IRC"].GetInt("verbosity", m_verbosity); | ||
194 | m_clientReporting = config.Configs["IRC"].GetInt("verbosity", 2) > 0; | ||
195 | m_clientReporting = config.Configs["IRC"].GetBoolean("report_clients", m_clientReporting); | ||
196 | |||
197 | // m_messageOutChannel = config.Configs["IRC"].GetInt("outchannel", m_messageOutChannel); | ||
198 | // m_messageInChannel = config.Configs["IRC"].GetInt("inchannel", m_messageInChannel); | ||
199 | m_relayPrivateChannels = config.Configs["IRC"].GetBoolean("relay_private_channels", m_relayPrivateChannels); | ||
200 | m_relayPrivateChannels = config.Configs["IRC"].GetBoolean("useworldcomm", m_relayPrivateChannels); //compat | ||
201 | m_relayChannel = config.Configs["IRC"].GetInt("relay_private_channel_in", m_relayChannel); | ||
202 | m_relayChannel = config.Configs["IRC"].GetInt("inchannel", m_relayChannel); | ||
203 | m_accessPassword = config.Configs["IRC"].GetString("access_password",m_accessPassword); | ||
204 | // m_useWorldComm = config.Configs["IRC"].GetBoolean("useworldcomm", m_useWorldComm); | ||
205 | |||
206 | if (m_server != null && m_baseNick != null && m_ircChannel != null) | ||
207 | { | ||
208 | if (m_randomizeNick) | ||
209 | { | ||
210 | m_nick = m_baseNick + Util.RandomClass.Next(1, 99); | ||
211 | } | ||
212 | m_enabled = true; | ||
213 | } | ||
214 | } | ||
215 | catch (Exception ex) | ||
216 | { | ||
217 | m_log.Error("[IRCConnector]: Incomplete IRC configuration, skipping IRC bridge configuration"); | ||
218 | m_log.DebugFormat("[IRCConnector] Incomplete IRC configuration: {0}", ex.ToString()); | ||
219 | } | ||
220 | |||
221 | if (null == m_watchdog) | ||
222 | { | ||
223 | m_watchdog = new Thread(WatchdogRun); | ||
224 | m_watchdog.Name = "IRCWatchdog"; | ||
225 | m_watchdog.IsBackground = true; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | public void Start() | ||
230 | { | ||
231 | if (!m_watchdog.IsAlive) | ||
232 | { | ||
233 | m_watchdog.Start(); | ||
234 | ThreadTracker.Add(m_watchdog); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | public void AddScene(Scene scene) | ||
239 | { | ||
240 | lock(m_syncConnect) m_scenes.Add(scene); | ||
241 | } | ||
242 | |||
243 | public bool Connect() | ||
244 | { | ||
245 | lock (m_syncConnect) | ||
246 | { | ||
247 | try | ||
248 | { | ||
249 | if (m_connected) return true; | ||
250 | |||
251 | m_tcp = new TcpClient(m_server, (int)m_port); | ||
252 | m_stream = m_tcp.GetStream(); | ||
253 | m_reader = new StreamReader(m_stream); | ||
254 | m_writer = new StreamWriter(m_stream); | ||
255 | |||
256 | m_log.DebugFormat("[IRCConnector]: Connected to {0}:{1}", m_server, m_port); | ||
257 | |||
258 | m_pinger = new Thread(new ThreadStart(PingRun)); | ||
259 | m_pinger.Name = "PingSenderThread"; | ||
260 | m_pinger.IsBackground = true; | ||
261 | m_pinger.Start(); | ||
262 | ThreadTracker.Add(m_pinger); | ||
263 | |||
264 | m_listener = new Thread(new ThreadStart(ListenerRun)); | ||
265 | m_listener.Name = "IRCConnectorListenerThread"; | ||
266 | m_listener.IsBackground = true; | ||
267 | m_listener.Start(); | ||
268 | ThreadTracker.Add(m_listener); | ||
269 | |||
270 | m_writer.WriteLine(m_user); | ||
271 | m_writer.Flush(); | ||
272 | m_writer.WriteLine(String.Format("NICK {0}", m_nick)); | ||
273 | m_writer.Flush(); | ||
274 | m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); | ||
275 | m_writer.Flush(); | ||
276 | m_log.Info("[IRCConnector]: Connection fully established"); | ||
277 | m_connected = true; | ||
278 | } | ||
279 | catch (Exception e) | ||
280 | { | ||
281 | m_log.ErrorFormat("[IRCConnector] cannot connect to {0}:{1}: {2}", | ||
282 | m_server, m_port, e.Message); | ||
283 | } | ||
284 | m_log.Debug("[IRCConnector] Connected"); | ||
285 | return m_connected; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | public void Reconnect() | ||
290 | { | ||
291 | m_connected = false; | ||
292 | try | ||
293 | { | ||
294 | m_listener.Abort(); | ||
295 | m_pinger.Abort(); | ||
296 | |||
297 | m_writer.Close(); | ||
298 | m_reader.Close(); | ||
299 | |||
300 | m_tcp.Close(); | ||
301 | } | ||
302 | catch (Exception) | ||
303 | { | ||
304 | } | ||
305 | |||
306 | if (m_enabled) | ||
307 | { | ||
308 | Connect(); | ||
309 | } | ||
310 | } | ||
311 | |||
312 | public void PrivMsg(string from, string region, string msg) | ||
313 | { | ||
314 | m_log.DebugFormat("[IRCConnector] Sending message to IRC from {0}: {1}", from, msg); | ||
315 | |||
316 | // One message to the IRC server | ||
317 | try | ||
318 | { | ||
319 | m_writer.WriteLine(m_privmsgformat, m_ircChannel, from, region, msg); | ||
320 | m_writer.Flush(); | ||
321 | m_log.InfoFormat("[IRCConnector]: PrivMsg {0} in {1}: {2}", from, region, msg); | ||
322 | } | ||
323 | catch (IOException) | ||
324 | { | ||
325 | m_log.Error("[IRCConnector]: Disconnected from IRC server.(PrivMsg)"); | ||
326 | Reconnect(); | ||
327 | } | ||
328 | catch (Exception ex) | ||
329 | { | ||
330 | m_log.ErrorFormat("[IRCConnector]: PrivMsg exception trap: {0}", ex.ToString()); | ||
331 | } | ||
332 | } | ||
333 | |||
334 | public void Send(string msg) | ||
335 | { | ||
336 | try | ||
337 | { | ||
338 | m_writer.WriteLine(msg); | ||
339 | m_writer.Flush(); | ||
340 | m_log.Info("IRC: Sent command string: " + msg); | ||
341 | } | ||
342 | catch (IOException) | ||
343 | { | ||
344 | m_log.Error("[IRCConnector]: Disconnected from IRC server.(PrivMsg)"); | ||
345 | Reconnect(); | ||
346 | } | ||
347 | catch (Exception ex) | ||
348 | { | ||
349 | m_log.ErrorFormat("[IRCConnector]: PrivMsg exception trap: {0}", ex.ToString()); | ||
350 | } | ||
351 | |||
352 | } | ||
353 | |||
354 | |||
355 | private Dictionary<string, string> ExtractMsg(string input) | ||
356 | { | ||
357 | //examines IRC commands and extracts any private messages | ||
358 | // which will then be reboadcast in the Sim | ||
359 | |||
360 | m_log.Info("[IRCConnector]: ExtractMsg: " + input); | ||
361 | Dictionary<string, string> result = null; | ||
362 | string regex = @":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)"; | ||
363 | Regex RE = new Regex(regex, RegexOptions.Multiline); | ||
364 | MatchCollection matches = RE.Matches(input); | ||
365 | |||
366 | // Get some direct matches $1 $4 is a | ||
367 | if ((matches.Count == 0) || (matches.Count != 1) || (matches[0].Groups.Count != 5)) | ||
368 | { | ||
369 | // m_log.Info("[IRCConnector]: Number of matches: " + matches.Count); | ||
370 | // if (matches.Count > 0) | ||
371 | // { | ||
372 | // m_log.Info("[IRCConnector]: Number of groups: " + matches[0].Groups.Count); | ||
373 | // } | ||
374 | return null; | ||
375 | } | ||
376 | |||
377 | result = new Dictionary<string, string>(); | ||
378 | result.Add("nick", matches[0].Groups[1].Value); | ||
379 | result.Add("user", matches[0].Groups[2].Value); | ||
380 | result.Add("channel", matches[0].Groups[3].Value); | ||
381 | result.Add("msg", matches[0].Groups[4].Value); | ||
382 | |||
383 | return result; | ||
384 | } | ||
385 | |||
386 | public void PingRun() | ||
387 | { | ||
388 | // IRC keep alive thread | ||
389 | // send PING ever 15 seconds | ||
390 | while (m_enabled) | ||
391 | { | ||
392 | try | ||
393 | { | ||
394 | if (m_connected == true) | ||
395 | { | ||
396 | m_writer.WriteLine(String.Format("PING :{0}", m_server)); | ||
397 | m_writer.Flush(); | ||
398 | Thread.Sleep(15000); | ||
399 | } | ||
400 | } | ||
401 | catch (IOException) | ||
402 | { | ||
403 | if (m_enabled) | ||
404 | { | ||
405 | m_log.Error("[IRCConnector]: Disconnected from IRC server.(PingRun)"); | ||
406 | Reconnect(); | ||
407 | } | ||
408 | } | ||
409 | catch (Exception ex) | ||
410 | { | ||
411 | m_log.ErrorFormat("[IRCConnector]: PingRun exception trap: {0}\n{1}", ex.ToString(), ex.StackTrace); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | |||
416 | static private Vector3 pos = new Vector3(128, 128, 20); | ||
417 | public void ListenerRun() | ||
418 | { | ||
419 | string inputLine; | ||
420 | |||
421 | while (m_enabled) | ||
422 | { | ||
423 | try | ||
424 | { | ||
425 | while ((m_connected) && ((inputLine = m_reader.ReadLine()) != null)) | ||
426 | { | ||
427 | // m_log.Info("[IRCConnector]: " + inputLine); | ||
428 | |||
429 | if (inputLine.Contains(m_ircChannel)) | ||
430 | { | ||
431 | Dictionary<string, string> data = ExtractMsg(inputLine); | ||
432 | // Any chat ??? | ||
433 | if (data != null) | ||
434 | { | ||
435 | OSChatMessage c = new OSChatMessage(); | ||
436 | c.Message = data["msg"]; | ||
437 | c.Type = ChatTypeEnum.Region; | ||
438 | c.Position = pos; | ||
439 | c.Channel = m_relayPrivateChannels ? m_relayChannel : 0; | ||
440 | c.From = data["nick"]; | ||
441 | c.Sender = null; | ||
442 | c.SenderUUID = UUID.Zero; | ||
443 | |||
444 | // is message "\001ACTION foo | ||
445 | // bar\001"? -> "/me foo bar" | ||
446 | if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION")) | ||
447 | c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9)); | ||
448 | |||
449 | m_log.DebugFormat("[IRCConnector] ListenerRun from: {0}, {1}", c.From, c.Message); | ||
450 | |||
451 | foreach (Scene scene in m_scenes) | ||
452 | { | ||
453 | c.Scene = scene; | ||
454 | scene.EventManager.TriggerOnChatBroadcast(this, c); | ||
455 | } | ||
456 | } | ||
457 | |||
458 | Thread.Sleep(150); | ||
459 | continue; | ||
460 | } | ||
461 | |||
462 | ProcessIRCCommand(inputLine); | ||
463 | Thread.Sleep(150); | ||
464 | } | ||
465 | } | ||
466 | catch (IOException) | ||
467 | { | ||
468 | if (m_enabled) | ||
469 | { | ||
470 | m_log.Error("[IRCConnector]: ListenerRun IOException. Disconnected from IRC server ??? (ListenerRun)"); | ||
471 | Reconnect(); | ||
472 | } | ||
473 | } | ||
474 | catch (Exception ex) | ||
475 | { | ||
476 | m_log.ErrorFormat("[IRCConnector]: ListenerRun exception trap: {0}\n{1}", ex.ToString(), ex.StackTrace); | ||
477 | } | ||
478 | } | ||
479 | } | ||
480 | |||
481 | public void BroadcastSim(string sender, string format, params string[] args) | ||
482 | { | ||
483 | try | ||
484 | { | ||
485 | OSChatMessage c = new OSChatMessage(); | ||
486 | c.From = sender; | ||
487 | c.Message = String.Format(format, args); | ||
488 | c.Type = ChatTypeEnum.Region; // ChatTypeEnum.Say; | ||
489 | c.Channel = m_relayPrivateChannels ? m_relayChannel : 0; | ||
490 | c.Position = new Vector3(128, 128, 20); | ||
491 | c.Sender = null; | ||
492 | c.SenderUUID = UUID.Zero; | ||
493 | |||
494 | m_log.DebugFormat("[IRCConnector] BroadcastSim from {0}: {1}", c.From, c.Message); | ||
495 | |||
496 | foreach (Scene scene in m_scenes) | ||
497 | { | ||
498 | c.Scene = scene; | ||
499 | scene.EventManager.TriggerOnChatBroadcast(this, c); | ||
500 | // // m_scene.EventManager.TriggerOnChatFromWorld(this, c); | ||
501 | // IWorldComm wComm = m_scene.RequestModuleInterface<IWorldComm>(); | ||
502 | // wComm.DeliverMessage(ChatTypeEnum.Region, m_messageInChannel, sender, UUID.Zero, c.Message); | ||
503 | // //IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
504 | // //wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); | ||
505 | |||
506 | } | ||
507 | } | ||
508 | catch (Exception ex) // IRC gate should not crash Sim | ||
509 | { | ||
510 | m_log.ErrorFormat("[IRCConnector]: BroadcastSim Exception Trap: {0}\n{1}", ex.ToString(), ex.StackTrace); | ||
511 | } | ||
512 | } | ||
513 | |||
514 | public void ProcessIRCCommand(string command) | ||
515 | { | ||
516 | // m_log.Debug("[IRCConnector]: ProcessIRCCommand:" + command); | ||
517 | |||
518 | string[] commArgs = new string[command.Split(' ').Length]; | ||
519 | string c_server = m_server; | ||
520 | |||
521 | commArgs = command.Split(' '); | ||
522 | if (commArgs[0].Substring(0, 1) == ":") | ||
523 | { | ||
524 | commArgs[0] = commArgs[0].Remove(0, 1); | ||
525 | } | ||
526 | |||
527 | if (commArgs[1] == "002") | ||
528 | { | ||
529 | // fetch the correct servername | ||
530 | // ex: irc.freenode.net -> brown.freenode.net/kornbluth.freenode.net/... | ||
531 | // irc.bluewin.ch -> irc1.bluewin.ch/irc2.bluewin.ch | ||
532 | |||
533 | c_server = (commArgs[6].Split('['))[0]; | ||
534 | m_server = c_server; | ||
535 | } | ||
536 | |||
537 | if (commArgs[0] == "ERROR") | ||
538 | { | ||
539 | m_log.ErrorFormat("[IRCConnector]: IRC SERVER ERROR: {0}", command); | ||
540 | } | ||
541 | |||
542 | if (commArgs[0] == "PING") | ||
543 | { | ||
544 | string p_reply = ""; | ||
545 | |||
546 | for (int i = 1; i < commArgs.Length; i++) | ||
547 | { | ||
548 | p_reply += commArgs[i] + " "; | ||
549 | } | ||
550 | |||
551 | m_writer.WriteLine(String.Format("PONG {0}", p_reply)); | ||
552 | m_writer.Flush(); | ||
553 | } | ||
554 | else if (commArgs[0] == c_server) | ||
555 | { | ||
556 | // server message | ||
557 | try | ||
558 | { | ||
559 | Int32 commandCode = Int32.Parse(commArgs[1]); | ||
560 | switch (commandCode) | ||
561 | { | ||
562 | case (int)ErrorReplies.NicknameInUse: | ||
563 | // Gen a new name | ||
564 | m_nick = m_baseNick + Util.RandomClass.Next(1, 99); | ||
565 | m_log.ErrorFormat("[IRCConnector]: IRC SERVER reports NicknameInUse, trying {0}", m_nick); | ||
566 | // Retry | ||
567 | m_writer.WriteLine(String.Format("NICK {0}", m_nick)); | ||
568 | m_writer.Flush(); | ||
569 | m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); | ||
570 | m_writer.Flush(); | ||
571 | break; | ||
572 | case (int)ErrorReplies.NotRegistered: | ||
573 | break; | ||
574 | case (int)Replies.EndOfMotd: | ||
575 | break; | ||
576 | } | ||
577 | } | ||
578 | catch (Exception) | ||
579 | { | ||
580 | } | ||
581 | } | ||
582 | else | ||
583 | { | ||
584 | // Normal message | ||
585 | string commAct = commArgs[1]; | ||
586 | switch (commAct) | ||
587 | { | ||
588 | case "JOIN": | ||
589 | eventIrcJoin(commArgs); | ||
590 | break; | ||
591 | case "PART": | ||
592 | eventIrcPart(commArgs); | ||
593 | break; | ||
594 | case "MODE": | ||
595 | eventIrcMode(commArgs); | ||
596 | break; | ||
597 | case "NICK": | ||
598 | eventIrcNickChange(commArgs); | ||
599 | break; | ||
600 | case "KICK": | ||
601 | eventIrcKick(commArgs); | ||
602 | break; | ||
603 | case "QUIT": | ||
604 | eventIrcQuit(commArgs); | ||
605 | break; | ||
606 | case "PONG": | ||
607 | break; // that's nice | ||
608 | } | ||
609 | } | ||
610 | } | ||
611 | |||
612 | public void eventIrcJoin(string[] commArgs) | ||
613 | { | ||
614 | string IrcChannel = commArgs[2]; | ||
615 | if (IrcChannel.StartsWith(":")) | ||
616 | IrcChannel = IrcChannel.Substring(1); | ||
617 | string IrcUser = commArgs[0].Split('!')[0]; | ||
618 | if (m_clientReporting) | ||
619 | BroadcastSim(IrcUser, "/me joins {0}", IrcChannel); | ||
620 | } | ||
621 | |||
622 | public void eventIrcPart(string[] commArgs) | ||
623 | { | ||
624 | string IrcChannel = commArgs[2]; | ||
625 | string IrcUser = commArgs[0].Split('!')[0]; | ||
626 | if (m_clientReporting) | ||
627 | BroadcastSim(IrcUser, "/me parts {0}", IrcChannel); | ||
628 | } | ||
629 | |||
630 | public void eventIrcMode(string[] commArgs) | ||
631 | { | ||
632 | string UserMode = ""; | ||
633 | for (int i = 3; i < commArgs.Length; i++) | ||
634 | { | ||
635 | UserMode += commArgs[i] + " "; | ||
636 | } | ||
637 | |||
638 | if (UserMode.Substring(0, 1) == ":") | ||
639 | { | ||
640 | UserMode = UserMode.Remove(0, 1); | ||
641 | } | ||
642 | } | ||
643 | |||
644 | public void eventIrcNickChange(string[] commArgs) | ||
645 | { | ||
646 | string UserOldNick = commArgs[0].Split('!')[0]; | ||
647 | string UserNewNick = commArgs[2].Remove(0, 1); | ||
648 | if (m_clientReporting) | ||
649 | BroadcastSim(UserOldNick, "/me is now known as {0}", UserNewNick); | ||
650 | } | ||
651 | |||
652 | public void eventIrcKick(string[] commArgs) | ||
653 | { | ||
654 | string UserKicker = commArgs[0].Split('!')[0]; | ||
655 | string UserKicked = commArgs[3]; | ||
656 | string IrcChannel = commArgs[2]; | ||
657 | string KickMessage = ""; | ||
658 | for (int i = 4; i < commArgs.Length; i++) | ||
659 | { | ||
660 | KickMessage += commArgs[i] + " "; | ||
661 | } | ||
662 | if (m_clientReporting) | ||
663 | BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); | ||
664 | if (UserKicked == m_nick) | ||
665 | { | ||
666 | BroadcastSim(m_nick, "Hey, that was me!!!"); | ||
667 | } | ||
668 | } | ||
669 | |||
670 | public void eventIrcQuit(string[] commArgs) | ||
671 | { | ||
672 | string IrcUser = commArgs[0].Split('!')[0]; | ||
673 | string QuitMessage = ""; | ||
674 | |||
675 | for (int i = 2; i < commArgs.Length; i++) | ||
676 | { | ||
677 | QuitMessage += commArgs[i] + " "; | ||
678 | } | ||
679 | if (m_clientReporting) | ||
680 | BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage); | ||
681 | } | ||
682 | |||
683 | public void Close() | ||
684 | { | ||
685 | m_writer.WriteLine(String.Format("QUIT :{0} to {1} wormhole to {2} closing", | ||
686 | m_nick, m_ircChannel, m_server)); | ||
687 | m_writer.Flush(); | ||
688 | |||
689 | m_connected = false; | ||
690 | m_enabled = false; | ||
691 | |||
692 | //listener.Abort(); | ||
693 | //pingSender.Abort(); | ||
694 | |||
695 | m_writer.Close(); | ||
696 | m_reader.Close(); | ||
697 | m_stream.Close(); | ||
698 | m_tcp.Close(); | ||
699 | } | ||
700 | |||
701 | protected void WatchdogRun() | ||
702 | { | ||
703 | while (m_enabled) | ||
704 | { | ||
705 | if (!m_connected) Connect(); | ||
706 | Thread.Sleep(15000); | ||
707 | } | ||
708 | } | ||
709 | } | ||
710 | } \ No newline at end of file | ||