using System; using System.Text; using System.Collections; using System.Threading; using TechBot.IRCLibrary; namespace TechBot.Library { public class IrcServiceOutput : IServiceOutput { public void WriteLine(MessageContext context, string message) { if (context is ChannelMessageContext) { Thread.Sleep (500); ChannelMessageContext channelContext = context as ChannelMessageContext; channelContext.Channel.Talk(message); } else if (context is UserMessageContext) { UserMessageContext userContext = context as UserMessageContext; userContext.User.Talk(message); } else { throw new InvalidOperationException(String.Format("Unhandled message context '{0}'", context.GetType())); } } } public class IrcTechBotService : TechBotService { private int port; private string hostname; private string channelnames; private string botname; private string password; private IrcClient m_IrcClient; private ArrayList channels = new ArrayList(); private bool isStopped = false; public IrcTechBotService(string hostname, int port, string channelnames, string botname, string password) : base (new IrcServiceOutput()) { this.hostname = hostname; this.port = port; this.channelnames = channelnames; this.botname = botname; if (password == null || password.Trim() == "") this.password = null; else this.password = password; } public override void Run() { //Call the base class base.Run(); m_IrcClient = new IrcClient(); m_IrcClient.Encoding = Encoding.GetEncoding("iso-8859-1"); m_IrcClient.OnConnect += new OnConnectHandler(m_IrcClient_OnConnect); m_IrcClient.OnConnectionLost += new OnConnectionLostHandler(m_IrcClient_OnConnectionLost); m_IrcClient.OnDisconnect += new OnDisconnectHandler(m_IrcClient_OnDisconnect); m_IrcClient.MessageReceived += new MessageReceivedHandler(client_MessageReceived); m_IrcClient.ChannelUserDatabaseChanged += new ChannelUserDatabaseChangedHandler(client_ChannelUserDatabaseChanged); Connect(); } void m_IrcClient_OnConnect() { Console.WriteLine("Connected..."); } private void Connect() { Console.WriteLine("Connecting to {0} port {1}", hostname, port); m_IrcClient.Connect(hostname, port); m_IrcClient.Register(botname, password, null); Console.WriteLine("Registered as {0}...", m_IrcClient.Nickname); /* Did we get the nick we wanted? */ if (m_IrcClient.Nickname != botname) { /* there must have been an existing one, kill it */ m_IrcClient.GhostNick(botname, password);; } JoinChannels(); while (!isStopped) { Thread.Sleep(1000); } PartChannels(); m_IrcClient.Diconnect(); } void m_IrcClient_OnDisconnect() { Console.WriteLine("Disconnected..."); } void m_IrcClient_OnConnectionLost() { //Dispose old connection Disconnect(); //Sleep for 1 minute Thread.Sleep(1000 * 60); //Try to reconnect Connect(); } private void Disconnect() { try { m_IrcClient.Diconnect(); } catch (Exception) { // } } public void Stop() { isStopped = true; } private void JoinChannels() { foreach (string channelname in channelnames.Split(new char[] { ';' })) { IrcChannel channel = m_IrcClient.JoinChannel(channelname); channels.Add(channel); System.Console.WriteLine(String.Format("Joined channel #{0}...", channel.Name)); } } private void PartChannels() { foreach (IrcChannel channel in channels) { m_IrcClient.PartChannel(channel, "Caught in the bitstream..."); System.Console.WriteLine(String.Format("Parted channel #{0}...", channel.Name)); } } private string GetMessageSource(MessageContext context) { if (context is ChannelMessageContext) { ChannelMessageContext channelContext = context as ChannelMessageContext; return String.Format("#{0}", channelContext.Channel.Name); } else if (context is UserMessageContext) { UserMessageContext userContext = context as UserMessageContext; return userContext.User.Nickname; } else { throw new InvalidOperationException(String.Format("Unhandled message context '{0}'", context.GetType())); } } private void ExtractMessage(string parameters, out string message) { int startIndex = parameters.IndexOf(':'); if (startIndex != -1) { message = parameters.Substring(startIndex + 1); } else { message = parameters; } } private bool GetChannelName(IrcMessage message, out string channelName) { if (message.Parameters == null || !message.Parameters.StartsWith("#")) { channelName = null; return false; } int index = message.Parameters.IndexOf(' '); if (index == -1) index = message.Parameters.Length; else index = index - 1; channelName = message.Parameters.Substring(1, index); return true; } private bool GetTargetNickname(IrcMessage message, out string nickname) { if (message.Parameters == null) { nickname = null; return false; } int index = message.Parameters.IndexOf(' '); if (index == -1) index = message.Parameters.Length; nickname = message.Parameters.Substring(0, index); Console.WriteLine("nickname: " + nickname); return true; } private bool ShouldAcceptMessage(IrcMessage message, out MessageContext context) { if (message.Command.ToUpper().Equals("PRIVMSG")) { string channelName; string nickname; if (GetChannelName(message, out channelName)) { foreach (IrcChannel channel in channels) { if (String.Compare(channel.Name, channelName, true) == 0) { context = new ChannelMessageContext(channel); return true; } } } else if (GetTargetNickname(message, out nickname)) { IrcUser targetUser = new IrcUser(m_IrcClient, nickname); if (String.Compare(targetUser.Nickname, botname, true) == 0) { IrcUser sourceUser = new IrcUser(m_IrcClient, message.PrefixNickname); context = new UserMessageContext(sourceUser); return true; } } } context = null; return false; } private void client_MessageReceived(IrcMessage message) { try { if (message.Command != null && message.Parameters != null) { string injectMessage; ExtractMessage(message.Parameters, out injectMessage); MessageContext context; if (ShouldAcceptMessage(message, out context)) { Console.WriteLine(String.Format("Injecting: {0} from {1}", injectMessage, GetMessageSource(context))); InjectMessage(context, injectMessage); } else { Console.WriteLine("Received: " + message.Line); } } else { Console.WriteLine("Received: " + message.Line); } } catch (Exception ex) { Console.WriteLine(String.Format("Exception: {0}", ex)); } } private void client_ChannelUserDatabaseChanged(IrcChannel channel) { } } }