jamin on March 4th, 2003

I’ve now got a simple IRC bot that I can control remotely. See previous stories to see the progression and get a feel for where this is going:

.NET Remoting with Mono
.NET Remoting with Mono Part II
Writing IRC bots in Perl and C#

Click below for the latest source code.

Main.cs:


using System;
using Sharkbite.Irc;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace TestCode.Irc
{
  public class GemsBotMain
  {
    public static void Main(string[] args)
    {
      string[] parameters = Util.ParseArgs( args );
      GemsBot bot = new GemsBot( parameters[0],
                                 parameters[1],
                                 parameters[2] );
      bot.connection.Connect();
      TcpChannel tcp_channel = new TcpChannel(8080);
      ChannelServices.RegisterChannel(tcp_channel);

      RemotingServices.Marshal(bot, "GemsBot");
      Console.WriteLine("GemsBot connected.");
      Console.ReadLine();
    }
  }
}

Util.cs:


using System;
using Sharkbite.Irc;
namespace TestCode.Irc
{
  public class Util
  {
    // Creates a n!u@h user id
    public static string BuildUserID ( UserInfo user )
    {
      return user.Nick + "!" + user.User + "@" + user.Hostname;
    }
    public static string[] ParseArgs ( string[] args )
    {
      string arg, value;
      // defaults
      string[] parameters = new string[] {"gems", "#kos", "boston.ma.us.galaxynet.org"};
      foreach (string s in args)
      {
        int idx = s.IndexOf( ":" );
        if (idx == -1){
          arg = s;
          value = "";
        } else {
          arg = s.Substring (0, idx);
          value = s.Substring (idx + 1);
        }
        switch ( arg )
        {
          case "/nick":
            parameters[0] = value;
            break;
          case "/channel":
            parameters[1] = value;
            break;
          case "/server":
            parameters[2] = value;
            break;
          default:
            //Usage();
            break;
        }
      }
      return parameters;
    }
  }
}

GemsBot.cs:


using System;
using Sharkbite.Irc;
using System.Text.RegularExpressions;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace TestCode.Irc
{
  public class GemsBot : MarshalByRefObject
  {
    public Connection connection;
    private string nick;
    private string channel;
    private string server;
    private Regex auto_op;
    public GemsBot( string nick, string channel, string server )
    {
      this.nick = nick;
      this.channel = channel;
      this.server = server;
      auto_op = new Regex( @"(?ix)skeez.*!~?jamin@.*.dsl.stlsmo.swbell.net|
                                  skeez.*!~?jamin@.*cec.wustl.edu",
                                  RegexOptions.Compiled);
      ConnectionArgs cargs = new ConnectionArgs( nick, server );
      connection = new Connection( cargs, false, false );
      // Set up our handlers
      connection.Listener.OnRegistered += new RegisteredEventHandler( OnRegistered );
      connection.Listener.OnJoin += new JoinEventHandler( OnJoin );
      connection.Listener.OnPublic += new PublicMessageEventHandler( OnPublic );
    }
    public override Object InitializeLifetimeService()
    {
      return null;
    }
    public void OnRegistered()
    {
      connection.Sender.Join( channel );
      Say( "Hey, " + channel + "!" );
    }
    public void OnJoin( UserInfo user, string channel )
    {
      string id = Util.BuildUserID( user );
      Log( "{0} has joined {1}", id, channel );
      if ( auto_op.IsMatch( id ) )
      {
        connection.Sender.ChangeChannelMode(
          channel,
          ModeAction.Add,
          ChannelMode.ChannelOperator,
          user.Nick
        );
      }
    }
    public void OnPublic( UserInfo user, string channel, string message )
    {
      Log( "<{0}> {1}", user.Nick, message );
    }
    public void Say( string text )
    {
      connection.Sender.PublicMessage( channel, text );
      Log( "<{0}> {1}", nick, text );
    }
    public void Me( string text )
    {
      connection.Sender.Action( channel, text );
      Log( "* {0} {1}", nick, text );
    }
    public void Join( string chnl )
    {
      channel = chnl;
      connection.Sender.Join( chnl );
    }
    public void Log( string format, params object[] arg )
    {
      Console.WriteLine( format, arg );
    }
  }
}

RemotingClient.cs:


using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Text.RegularExpressions;
using Sharkbite.Irc;
namespace TestCode.Irc
{
  public class RemotingClient
  {
    public static void Main(string [] args)
    {
      TcpChannel chan = new TcpChannel();
      ChannelServices.RegisterChannel(chan);
      string command;
      Regex rCommand = new Regex( @"(?<cmd>w+)s+(?<args>.*)" ,
                                  RegexOptions.Compiled );
      Match m;
      GemsBot obj = (GemsBot) Activator.GetObject(
        typeof(TestCode.Irc.GemsBot),
        "tcp://localhost:8080/GemsBot" );
      while (true)
      {
        string remote_cmd;
        string remote_args;
        Console.Write("RemoteIrc command> ");
        command = Console.ReadLine();
        if (command == "quit" || command == "exit")
        {
          break;
        }
        else
        {
          // Split the text into the command and the arguments
          m = rCommand.Match( command );
          if ( m.Success )
          {
            remote_cmd = m.Groups["cmd"].Value;
            remote_args = m.Groups["args"].Value;
            switch ( remote_cmd )
            {
              case "say":
                obj.Say( remote_args );
                break;
              case "me":
                obj.Me( remote_args );
                break;
              case "join":
                obj.Join( remote_args );
                break;
              default:
                Console.WriteLine("Unknown Command.  Try again...");
                break;
            }
          }
        }
      }
    }
  }
}

Makefile:


CSC=mcs --debug
default: all
Main.exe: Main.cs GemsBot.dll Util.dll
	$(CSC) /r:IRC.dll /r:GemsBot.dll /r:Util.dll /r:System.Runtime.Remoting $<
RemotingClient.exe: RemotingClient.cs GemsBot.dll
	$(CSC) /r:GemsBot.dll /r:System.Runtime.Remoting $<
Util.dll: Util.cs
	$(CSC) /r:IRC.dll /target:library $<
GemsBot.dll: GemsBot.cs Util.dll
	$(CSC) /r:IRC.dll /r:Util.dll /target:library $<
all: GemsBot.dll Util.dll Main.exe RemotingClient.exe
clean:
	rm -f *.dll *.exe

Tags: