using System; using System.Net.Sockets; using System.Threading; using System.IO; using System.Collections; using Server; using Knives.Utils; namespace Knives.Chat3 { public enum IrcColor { White = 0, Black = 1, Blue = 2, Green = 3, LightRed = 4, Brown = 5, Purple = 6, Orange = 7, Yellow = 8, LightGreen = 9, Cyan = 10, LightCyan = 11, LightBlue = 12, Pink = 13, Grey = 14, LightGrey = 15, }; public class IrcConnection { private static IrcConnection s_Connection = new IrcConnection(); public static IrcConnection Connection{ get{ return s_Connection; } } private TcpClient c_Tcp; private Thread c_Thread; private StreamReader c_Reader; private StreamWriter c_Writer; private bool c_Connecting, c_Connected; private int c_Attempts; private DateTime c_LastPong; public bool Connecting{ get{ return c_Connecting; } } public bool Connected{ get{ return c_Connected; } } public bool HasMoreAttempts{ get{ return c_Attempts <= Data.IrcMaxAttempts; } } public IrcConnection() { } public void Connect( Mobile m ) { Data data = Data.GetData( m ); if ( c_Connecting ) { m.SendMessage( data.SystemC, General.Local(102) ); return; } if ( c_Connected ) { m.SendMessage( data.SystemC, General.Local(103) ); return; } Connect(); } public void Connect() { new Thread( new ThreadStart( ConnectTcp ) ).Start(); } public void CancelConnect() { c_Attempts = Data.IrcMaxAttempts; } private void Reconnect() { c_Attempts++; if ( !HasMoreAttempts ) { c_Attempts = 1; BroadcastSystem( General.Local(104) ); return; } BroadcastSystem( General.Local(105) + c_Attempts ); Connect(); } private void ConnectTcp() { try{ c_Tcp = new TcpClient( Data.IrcServer, Data.IrcPort ); } catch { BroadcastSystem( General.Local(106) ); Reconnect(); return; } ConnectStream(); } private void ConnectStream() {try{ c_Connecting = true; c_LastPong = DateTime.Now; c_Reader = new StreamReader(c_Tcp.GetStream(), System.Text.Encoding.Default); c_Writer = new StreamWriter(c_Tcp.GetStream(), System.Text.Encoding.Default); BroadcastSystem( General.Local(107) ); SendMessage(String.Format("USER {0} 1 * :Hello!", Data.IrcNick)); SendMessage(String.Format("NICK {0}", Data.IrcNick)); c_Thread = new Thread(new ThreadStart(ReadStream)); c_Thread.Start(); Server.Timer.DelayCall( TimeSpan.FromSeconds( 15.0 ), new Server.TimerCallback( Names ) ); foreach (Data data in Data.Datas.Values) if (data.Mobile.HasGump(typeof(SetupGump))) General.RefreshGump(data.Mobile, typeof(SetupGump)); }catch{ Errors.Report( String.Format( "IrcConnection-> ConnectStream" ) ); } } private void Names() { if (c_Connected) SendMessage("NAMES " + Data.IrcRoom); else return; Server.Timer.DelayCall( TimeSpan.FromSeconds( 15.0 ), new Server.TimerCallback( Names ) ); } private void PingPong(string str) { if (!c_Connecting && !c_Connected) return; if (str.IndexOf("PING") != -1) str = str.Replace("PING", "PONG"); else str = str.Replace("PONG", "PING"); SendMessage( str ); } public void SendMessage( string msg ) { try{ BroadcastRaw( msg ); c_Writer.WriteLine( msg ); c_Writer.Flush(); }catch{ Disconnect(); } } public void SendUserMessage( Mobile m, string msg ) { if ( !Connected ) return; msg = OutParse( m, m.Name + ": " + msg ); s_Connection.SendMessage( String.Format( "PRIVMSG {0} : {1}", Data.IrcRoom, msg )); BroadcastRaw( String.Format( "PRIVMSG {0} : {1}", Data.IrcRoom, msg ) ); } private string OutParse( Mobile m, string str ) { if ( m.AccessLevel != AccessLevel.Player ) return str = '\x0003' + ((int)Data.IrcStaffColor).ToString() + str; return str; } private void BroadcastSystem( string msg ) { foreach( Data data in Data.Datas.Values ) if ( data.Channels.Contains("IRC") && !data.Banned ) data.Mobile.SendMessage( data.SystemC, msg ); } private void Broadcast( string name, string msg ) { if (!(Channel.GetByName("IRC") is IRC)) return; ((IRC)Channel.GetByName("IRC")).Broadcast(name, msg); } private void Broadcast( Mobile m, string msg ) { } private void BroadcastRaw( string msg ) { foreach( Data data in Data.Datas.Values ) if ( data.IrcRaw ) data.Mobile.SendMessage( data.SystemC, "RAW: " + msg ); } private void ReadStream() {try{ string input = ""; while( c_Thread.IsAlive ) { input = c_Reader.ReadLine(); if ( input == null ) break; HandleInput( input ); } Disconnect(); }catch{ Disconnect(); } } private void HandleInput( string str ) {try{ if (str == null) return; BroadcastRaw( str ); if ( str.IndexOf( "PONG" ) != -1 || str.IndexOf("PING") != -1 ) { PingPong( str ); return; } if ( str.IndexOf( "353" ) != -1 ) { BroadcastRaw( General.Local(109) ); int index = str.ToLower().IndexOf( Data.IrcRoom.ToLower() ) + Data.IrcRoom.Length + 2; if ( index == 1 ) return; string strList = str.Substring( index, str.Length-index ); string[] strs = strList.Trim().Split( ' ' ); Data.IrcList.Clear(); Data.IrcList.AddRange( strs ); Data.IrcList.Remove( Data.IrcNick ); } if (str.IndexOf("001") != -1 && c_Connecting) { c_Connected = true; c_Connecting = false; BroadcastSystem(General.Local(108)); c_Attempts = 1; SendMessage(String.Format("JOIN {0}", Data.IrcRoom)); foreach (Data data in Data.Datas.Values) if (data.Mobile.HasGump(typeof(SetupGump))) General.RefreshGump(data.Mobile, typeof(SetupGump)); } if (str.Length > 300) return; if (str.IndexOf("PRIVMSG") != -1) { string parOne = str.Substring( 1, str.IndexOf( "!" )-1 ); string parThree = str.Substring( str.IndexOf( "!" )+1, str.Length-str.IndexOf("!")-(str.Length-str.IndexOf("PRIVMSG"))-1); int index = 0; index = str.ToLower().IndexOf( Data.IrcRoom.ToLower() ) + Data.IrcRoom.Length + 2; if ( index == 1 ) return; string parTwo = str.Substring( index, str.Length-index ); if ( parTwo.IndexOf( "ACTION" ) != -1 ) { index = parTwo.IndexOf( "ACTION" ) + 7; parTwo = parTwo.Substring( index, parTwo.Length-index ); str = String.Format( "<{0}> {1} {2}", Data.IrcRoom, parOne, parTwo ); } else str = String.Format( "<{0}> {1}: {2}", Data.IrcRoom, parOne, parTwo ); Broadcast( parOne, str ); } } catch (Exception e) { Errors.Report(String.Format("IrcConnection-> HandleInput")); Console.WriteLine(e.Message); }} public void Disconnect() { Disconnect( true ); } public void Disconnect(bool reconn) { try { if (c_Connected) BroadcastSystem(General.Local(110)); c_Connected = false; c_Connecting = false; if (c_Thread != null) { c_Thread.Abort(); c_Thread = null; } if (c_Reader != null) c_Reader.Close(); if (c_Writer != null) c_Writer.Close(); if (c_Tcp != null) c_Tcp.Close(); if (reconn) Reconnect(); foreach (Data data in Data.Datas.Values) if (data.Mobile.HasGump(typeof(SetupGump))) General.RefreshGump(data.Mobile, typeof(SetupGump)); } catch { Errors.Report(String.Format("IrcConnection-> Disconnect")); } } } }